GHC often depicts H98 datatypes as GADTs when it shouldn't
(Spun off from D3880.)
There are at least a couple of points in the GHC codebase where poor decisions are made regarding whether to depict a datatype using H98 syntax or GADT syntax. In particular:
- When reifying a datatype in Template Haskell, some complicated heuristics are used to determine whether a datatype is reified with
(Rec)GadtC
or not (seeNote [Reifying GADT data constructors]
inTcSplice
for the horrifying details). But these heuristics are far from perfect, as they will cause some vanilla datatypes to be reified as GADTs (e.g.,data T a = (a ~ Int) => MkT
). - When pretty-printing a datatype (for instance, via the
:info
command in GHCi), GHC also chooses to sometimes depict vanilla datatypes as GADTs. For instance:
λ> :set -XExistentialQuantification
λ> data Foo a = Show a => Foo
λ> :i Foo
type role Foo nominal
data Foo a where
Foo :: Show a => Foo a
Foo
is depicted as a GADT, despite the fact that we didn't use GADT syntax.
There might be other places in the code that exhibit these symptoms too—we should take a closer look.
I use the phrase "poor decisions" above since GHC really does have the right info it needs to make the correct decisions. That info is in the form of the isGadtSyntaxTyCon
, which conveniently recalls whether a datatype was declared with GADT syntax or not. With this, we should be able to eliminate the flawed heuristics that GHC is currently using and accurately depict datatypes the way users wrote them.
Trac metadata
Trac field | Value |
---|---|
Version | 8.2.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |