The current diagnostic reporting infrastructure requires maintaining by hand a mapping from the TypeError and Warning types into another pair of monster ErrorName and WarningName types. This is used both in reporting (it is shown in brackets) and to control what options should be enabled/disabled/made fatal. While the mapping doesn't have to be injective, this basically blesses the names of the Warning constructors as they were when the Name infrastructure was added as part of the backwards-compatibility surface.
I think that instead, diagnostics should have unique, randomly-assigned codes. These should be what is presented to the user, and should be indexed in the documentation, but we should never ingest them. We can look at how GHC assigns codes for inspiration on how to keep them unique across versions.
To control warnings, we should invent a new WarningFlag type that actually controls what (group of) warnings should be enabled, and which warnings should be errors. These should be coarser than the Warning constructors and ideally also have shorter names. We can then (again looking at GHC for inspiration) write functions TypeError -> DiagnosticReason and Warning -> DiagnosticReason into a type
data DiagnosticReason
= Error -- ^ Always an error, including "error-warnings".
| WarningWithFlags (List1 WarningFlag) -- ^ A warning affected by the given flags.
which can then be post-processed by a function PragmaOptions -> DiagnosticReason -> Severity to e.g. set a warning's severity to "ignored" or "error" depending.
The current diagnostic reporting infrastructure requires maintaining *by hand* a mapping from the `TypeError` and `Warning` types into another pair of monster `ErrorName` and `WarningName` types. This is used both in reporting (it is shown in brackets) and to control what options should be enabled/disabled/made fatal. While the mapping doesn't have to be injective, this basically blesses the names of the `Warning` constructors as they were when the `Name` infrastructure was added as part of the backwards-compatibility surface.
I think that instead, diagnostics should have unique, randomly-assigned *codes*. These should be what is *presented* to the user, and should be indexed in the documentation, but we should never *ingest* them. [We can look at how GHC assigns codes for inspiration](https://github.com/ghc/ghc/blob/master/compiler/GHC/Types/Error/Codes.hs) on how to keep them unique across versions.
To control warnings, we should invent a new `WarningFlag` type that actually controls what (group of) warnings should be enabled, and which warnings should be errors. These should be coarser than the `Warning` constructors and ideally also have shorter names. We can then (again looking at GHC for inspiration) write functions `TypeError -> DiagnosticReason` and `Warning -> DiagnosticReason` into a type
```haskell
data DiagnosticReason
= Error -- ^ Always an error, including "error-warnings".
| WarningWithFlags (List1 WarningFlag) -- ^ A warning affected by the given flags.
```
which can then be post-processed by a function `PragmaOptions -> DiagnosticReason -> Severity` to e.g. set a warning's severity to "ignored" or "error" depending.