Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

Allow nested foralls and contexts in prefix GADT constructors
This issue tracks the implementation of GHC Proposal [#402](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0402-gadt-syntax.rst) "Stable GADT constructor syntax". Subtickets: * [ ] #27423 "Parentheses in prefix GADT constructors" * [ ] #27424 "Curried contexts in prefix GADT constructors" * [ ] #27425 "Refactor `ConDeclGADT` to allow nested foralls and contexts" * [ ] #27426 "Support nested foralls and contexts in `DataCon`" ---- Currently, prefix GADT constructors are [very particular](https://gitlab.haskell.org/ghc/ghc/-/issues/18191) about where `forall`s and contexts are permitted in their types. In particular, the very beginning of a prefix GADT type can have an optional `forall`, followed by an optional context, followed by the rest of the type. Any other `forall`s or contexts that appear between argument types or the result type are rejected. For example, GHC does not permit this: ```hs data T a where MkT :: Int -> forall a. T a ``` This is rather surprising, even to [users who aren't me](https://gitlab.haskell.org/ghc/ghc/-/issues/14320). Fundamentally, there is no reason why this has to be the case. In fact, having nested `forall`s is an implicit requirement an already accepted GHC proposal, [A syntax for visible dependent quantification](https://github.com/ghc-proposals/ghc-proposals/blob/8f6a35a5ea4b5477aa6ae6fd124ac209e0327809/proposals/0081-forall-arrow.rst#a-syntax-for-visible-dependent-quantification). Although !378 implemented most of this proposal, there is one part that it deliberately did _not_ implement, namely: > A data constructor can use `forall ... ->` in its type (as given in GADT-syntax) or arguments, but any use of such a constructor in terms (as opposed to in a type) will be an error. Without having the ability to use nested `forall`s in prefix GADT constructors, however, this feature is of limited utility. This is because you would be able to write this: ```hs data VDQ a where MkVDQ :: forall a -> Int -> VDQ a ``` However, you would not be able to make a simple rearrangement of the arguments like this: ```hs data VDQ' a where MkVDQ' :: Int -> forall a -> VDQ a -- Nested forall! Rejected. ``` So why doesn't today's GHC permit nested `forall`s/contexts in GADT constructors? Mainly because of engineering concerns. Various data structurs in the internals of GHC assume that all `forall`'d type variables and constraint arguments all occur upfront. This assumption is baked into the design of `ConDeclGADT` and `DataCon`, among other things. How should we go about relaxing this restriction? While I haven't worked out the details completely yet, at minimum the following will need to happen: 1. The representation of arguments in prefix `ConDeclGADT`s will need to change. Currently, the `con_args` field of `ConDeclGADT` uses `HsConDeclDetails` to represent the argument types of the constructor. This currently assumes that each argument is a `BangType`, however. In order to make this accommodate nested `forall`s and contexts, however, we will likely need a richer data structure. Something like: ```hs data FunArg pass = AnonArg (HsScaled pass (LBangType pass)) | ForallArg (HsForAllTelescope pass) | ContextArg (LHsContext pass) ``` If we do this, then we can likely get rid of `con_forall` and `con_qvars`, which currently store the leading `forall`s and context. Well, except that isn't quite right—GADT constructor types obey the `forall`-or-nothing rule, and as a result, leading `forall`s are special. Bah. I'll have to think carefully about how to do this right. Note that all of this only really applies to _prefix_ GADT constructors. _Record_ GADT constructors, on the other hand, can't really have nested `forall`s or contexts due to the syntax that they use. I suppose this means we might need a different AST form for record GADT constructors than we do for prefix GADT constructors. Hm. 2. The way that user-written arguments are represented in `DataCon`s will need to change. Currently, `DataCon` looks like this: ```hs data DataCon = MkData { ... , dcUnivTyVars :: [TyVar] , dcExTyCoVars :: [TyCoVar] , dcUserTyVarBinders :: [InvisTVBinder] , dcEqSpec :: [EqSpec] , dcOtherTheta :: ThetaType , dcOrigArgTys :: [Type] , ... } ``` For the most part, this corresponds exactly to how the data type worker looks. It must have the universally quantified type variables (`dcUnivTyVars`), followed by the existentially quantified type variables (`dcExTyCoVars`), followed by the context arguments (`dcEqSpec` + `dcOtherTheta`), finally followed by the visible arguments (`dcOrigArgTys`), in exactly that order. The exception to that rule is `dcUserTyVarBinders`, which remembers the order in which the user quantifies type variables in a GADT constructor. This information is not for the benefit of the worker, but for the wrapper. There is some amount of type variable swizzling performed in `GHC.Types.Id.Make.mkDataConRep` to ensure that the user-written order in `dcUserTyVarBinders` is rearranged to the universals-then-existentials order that the worker expects. If we permit nested `forall`s and contexts, the first step is to figure out how to change `DataCon` to represent it. I imagine that we will need to replace `dcUserTyVarBinders` with something more general: ```hs { ... , dcUserTyCoBinders :: [TyCoBinder] , ... } ``` We will need `TyCoBinder`s because the `forall`s and contexts can be intermixed with visible argument types, and moreover, these can happen in basically any order. What's interesting about this change is `dcUserTyCoBinders` will store _all_ of the arguments to a `DataCon`, which will technically make `dcUnivTyVars`, `dcExTyCoVars`, `dcEqSpec`, `dcOtherTheta`, and `dcOrigArgTys` redundant. Still, we might consider keeping some (or all) of these fields anyway, since it could be more efficient to cache them rather than repeatedly computing them from the `dcUserTyCoBinders`. 3. We will need to update Template Haskell's representation of prefix GADTs, which is insufficient to represent nested `forall`s and contexts: ```hs data Con = ... | ForallC [TyVarBndr] Cxt Con | GadtC [Name] [BangType] Type | ... ``` It is unlikely that we will be able to make this work without redesigning `Con` to some extend. @rae suggests the following design: ```hs data Dec = ... | DataD ... Cons ... | NewtypeD ... Cons ... -- Alternatively, ... (Either H98Con GadtCon) ... if we want to really -- enforce the invariant that a newtype has exactly one data constructor data Cons = H98Cons [H98Con] | GadtCons [GadtCon] data H98Con = H98Con (Maybe [TyVarBndr]) (Maybe Cxt) Name H98ConBody data H98ConBody = NormalC ... | InfixC ... | RecC ... data GadtCon = GadtCon [Name] GadtConBody data GadtConBody = GadtC [FunArg ()] Type | RecGadtC [FunArg Name] Type data FunArg name = FunArg name Multiplicity Bang Type | ForallArg [TyVarBndr] | CxtArg Cxt ```
issue