Skip to content

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:

  1. When reifying a datatype in Template Haskell, some complicated heuristics are used to determine whether a datatype is reified with (Rec)GadtC or not (see Note [Reifying GADT data constructors] in TcSplice 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).
  2. 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
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information