Andrei Borzenkov pushed to branch wip/sand-witch/27423-gadt-parens at Glasgow Haskell Compiler / GHC
Commits:
-
52ecaabb
by Andrei Borzenkov at 2026-08-13T14:13:16+04:00
4 changed files:
- compiler/GHC/Hs/Decls.hs
- compiler/Language/Haskell/Syntax/Type.hs
- docs/users_guide/exts/gadt_syntax.rst
- testsuite/tests/printer/T27423c.hs
Changes:
| ... | ... | @@ -974,19 +974,21 @@ pprConDecl (ConDeclGADT { con_names = cons |
| 974 | 974 | , con_mb_cxt = mcxt, con_g_args = args
|
| 975 | 975 | , con_res_ty = res_ty, con_modifiers = mods, con_doc = doc })
|
| 976 | 976 | = pprMaybeWithDoc doc $ pprLHsModifiers mods <+> ppr_con_names (toList cons) <+> dcolon
|
| 977 | - <+> (ppr_outer_bndrs <+> ppr_inner_bndrs (
|
|
| 977 | + <+> sep [ppr_outer_bndrs, ppr_inner_bndrs (
|
|
| 978 | 978 | sep [ pprLHsContext mcxt,
|
| 979 | - sep (ppr_args args ++ [ppr res_ty])]))
|
|
| 979 | + sep (ppr_args args ++ [ppr res_ty])])]
|
|
| 980 | 980 | where
|
| 981 | 981 | ppr_args (PrefixConGADT _ args) = map (pprHsConDeclFieldWith (\arr tyDoc -> tyDoc <+> pprHsModifiedFunArr arr)) args
|
| 982 | 982 | ppr_args (RecConGADT _ fields) = [pprHsConDeclRecFields (unLoc fields) <+> arrow]
|
| 983 | 983 | |
| 984 | - -- pprint all parenthisis and foralls, so parse == parse . ppr . parse
|
|
| 984 | + -- pprint all parentheses and foralls, so parse == parse . ppr . parse
|
|
| 985 | 985 | ppr_inner_bndrs :: SDoc -> SDoc
|
| 986 | 986 | ppr_inner_bndrs tyDoc = foldr ppr_inner_bndr (tyDoc <> close_parens) inner_bndrs
|
| 987 | 987 | |
| 988 | 988 | ppr_inner_bndr (L _ HsGadtPar{}) rest = lparen <> rest
|
| 989 | - ppr_inner_bndr (L _ (HsGadtForAll _ tele)) rest = pprHsForAllTelescope tele <+> rest
|
|
| 989 | + ppr_inner_bndr (L _ (HsGadtForAll _ tele)) rest
|
|
| 990 | + | HsForAllInvis {hsf_invis_bndrs=[]} <- tele = empty_forall <+> rest
|
|
| 991 | + | otherwise = pprHsForAllTelescope tele <+> rest
|
|
| 990 | 992 | |
| 991 | 993 | -- for each open paren generate a closed one
|
| 992 | 994 | close_parens = hcat [ rparen | L _ HsGadtPar{} <- inner_bndrs ]
|
| ... | ... | @@ -997,10 +999,12 @@ pprConDecl (ConDeclGADT { con_names = cons |
| 997 | 999 | ppr_outer_bndrs
|
| 998 | 1000 | | HsOuterExplicit{hso_bndrs = []} <- outer_bndrs
|
| 999 | 1001 | , not (null inner_bndrs)
|
| 1000 | - = forAllLit <> dot
|
|
| 1002 | + = empty_forall
|
|
| 1001 | 1003 | | otherwise
|
| 1002 | 1004 | = pprHsOuterSigTyVarBndrs outer_bndrs
|
| 1003 | 1005 | |
| 1006 | + empty_forall = forAllLit <> dot
|
|
| 1007 | + |
|
| 1004 | 1008 | ppr_con_names :: (OutputableBndr a) => [GenLocated l a] -> SDoc
|
| 1005 | 1009 | ppr_con_names = pprWithCommas (pprPrefixOcc . unLoc)
|
| 1006 | 1010 |
| ... | ... | @@ -393,17 +393,15 @@ data HsForAllTelescope pass |
| 393 | 393 | }
|
| 394 | 394 | | XHsForAllTelescope !(XXHsForAllTelescope pass)
|
| 395 | 395 | |
| 396 | --- A type for interleaved GADT foralls and prefixes, inspired by HsArg
|
|
| 397 | ---
|
|
| 398 | --- `HsGadtPar` is only usefull for pretty-printing/exact-printing for recovering
|
|
| 399 | --- parenthisis interleaved with foralls.
|
|
| 396 | +-- | A type for interleaved GADT foralls and parentheses, inspired by HsArg.
|
|
| 400 | 397 | --
|
| 401 | 398 | -- Here's an example:
|
| 402 | 399 | --
|
| 403 | 400 | -- data D where
|
| 404 | --- MkD :: forall a b. ( forall c. forall d. ( forall. ...
|
|
| 405 | --- โ โ โ โ โ โ
|
|
| 406 | --- 1 2 3 4 5 6
|
|
| 401 | +-- MkD :: forall x y. -- these go to the `con_outer_bndrs` field
|
|
| 402 | +-- forall a b. ( forall c. forall d. ( forall. ...
|
|
| 403 | +-- โ โ โ โ โ โ
|
|
| 404 | +-- 1 2 3 4 5 6
|
|
| 407 | 405 | --
|
| 408 | 406 | -- That would correspond to a list
|
| 409 | 407 | --
|
| ... | ... | @@ -414,12 +412,15 @@ data HsForAllTelescope pass |
| 414 | 412 | -- 5 โ , HsGadtPar
|
| 415 | 413 | -- 6 โ , HsGadtForAll
|
| 416 | 414 | -- , ...]
|
| 417 | ---
|
|
| 418 | --- We can always recover parenthisis structure because they must close after
|
|
| 419 | --- return type.
|
|
| 420 | 415 | data HsGadtArg pass
|
| 421 | 416 | = HsGadtForAll !(XGadtForAll pass) (HsForAllTelescope pass)
|
| 422 | 417 | | HsGadtPar !(XGadtPar pass)
|
| 418 | + -- ^ `HsGadtPar` is only usefull for pretty-printing/exact-printing for recovering
|
|
| 419 | + -- parenthisis interleaved with foralls.
|
|
| 420 | + --
|
|
| 421 | + -- This approach differs from `HsPar`, which wraps the inner expression as if
|
|
| 422 | + -- surrounding it with parentheses. We can ditch the `HsPar` approach because
|
|
| 423 | + -- we know that all parentheses will be closed after the return type.
|
|
| 423 | 424 | | XHsGadtArg !(XXGadtArg pass)
|
| 424 | 425 | |
| 425 | 426 | type LHsGadtArg pass = XRec pass (HsGadtArg pass)
|
| ... | ... | @@ -201,12 +201,12 @@ syntactically allowed. Some further various observations about this grammar: |
| 201 | 201 | something like ``MkS :: Int -> (forall a. a) -> S`` is allowed, since
|
| 202 | 202 | parentheses separate the ``forall`` from the ``->``.)
|
| 203 | 203 | |
| 204 | -- Furthermore, GADT constructors do not permit outermost parentheses that
|
|
| 205 | - surround the ``foralls`` or ``opt_ctxt``, if at least one of them are
|
|
| 206 | - used. For example, ``MkU :: (forall a. a -> U)`` would be rejected, since
|
|
| 207 | - it would treat the ``forall`` as being nested.
|
|
| 204 | +- GADT constructors permit outermost parentheses that surround the ``foralls``
|
|
| 205 | + or ``opt_ctxt``, as well as interleaved parentheses between multiple
|
|
| 206 | + ``foralls``. For example, ``MkU :: (forall a. a -> U)`` is accepted, as is
|
|
| 207 | + ``MkW :: forall a. (forall b. a -> b -> W)``.
|
|
| 208 | 208 | |
| 209 | - Note that it is acceptable to use parentheses in a ``prefix_gadt_body``.
|
|
| 209 | + Note that it is also acceptable to use parentheses in a ``prefix_gadt_body``.
|
|
| 210 | 210 | For instance, ``MkV1 :: forall a. (a) -> (V1)`` is acceptable, as is
|
| 211 | 211 | ``MkV2 :: forall a. (a -> V2)``.
|
| 212 | 212 |
| ... | ... | @@ -18,6 +18,7 @@ data S a where |
| 18 | 18 | MkS :: (forall a. S a)
|
| 19 | 19 | MkS2 :: forall. (forall a. S a)
|
| 20 | 20 | MkS3 :: forall. forall a. S a
|
| 21 | + MkS4 :: forall a. forall. forall b. forall. forall. forall c. S a
|
|
| 21 | 22 | |
| 22 | 23 | data U a where
|
| 23 | 24 | MkU :: (Show a => U a)
|