[Git][ghc/ghc][wip/sand-witch/27423-gadt-parens] Address comments
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 Address comments - - - - - 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: ===================================== compiler/GHC/Hs/Decls.hs ===================================== @@ -974,19 +974,21 @@ pprConDecl (ConDeclGADT { con_names = cons , con_mb_cxt = mcxt, con_g_args = args , con_res_ty = res_ty, con_modifiers = mods, con_doc = doc }) = pprMaybeWithDoc doc $ pprLHsModifiers mods <+> ppr_con_names (toList cons) <+> dcolon - <+> (ppr_outer_bndrs <+> ppr_inner_bndrs ( + <+> sep [ppr_outer_bndrs, ppr_inner_bndrs ( sep [ pprLHsContext mcxt, - sep (ppr_args args ++ [ppr res_ty])])) + sep (ppr_args args ++ [ppr res_ty])])] where ppr_args (PrefixConGADT _ args) = map (pprHsConDeclFieldWith (\arr tyDoc -> tyDoc <+> pprHsModifiedFunArr arr)) args ppr_args (RecConGADT _ fields) = [pprHsConDeclRecFields (unLoc fields) <+> arrow] - -- pprint all parenthisis and foralls, so parse == parse . ppr . parse + -- pprint all parentheses and foralls, so parse == parse . ppr . parse ppr_inner_bndrs :: SDoc -> SDoc ppr_inner_bndrs tyDoc = foldr ppr_inner_bndr (tyDoc <> close_parens) inner_bndrs ppr_inner_bndr (L _ HsGadtPar{}) rest = lparen <> rest - ppr_inner_bndr (L _ (HsGadtForAll _ tele)) rest = pprHsForAllTelescope tele <+> rest + ppr_inner_bndr (L _ (HsGadtForAll _ tele)) rest + | HsForAllInvis {hsf_invis_bndrs=[]} <- tele = empty_forall <+> rest + | otherwise = pprHsForAllTelescope tele <+> rest -- for each open paren generate a closed one close_parens = hcat [ rparen | L _ HsGadtPar{} <- inner_bndrs ] @@ -997,10 +999,12 @@ pprConDecl (ConDeclGADT { con_names = cons ppr_outer_bndrs | HsOuterExplicit{hso_bndrs = []} <- outer_bndrs , not (null inner_bndrs) - = forAllLit <> dot + = empty_forall | otherwise = pprHsOuterSigTyVarBndrs outer_bndrs + empty_forall = forAllLit <> dot + ppr_con_names :: (OutputableBndr a) => [GenLocated l a] -> SDoc ppr_con_names = pprWithCommas (pprPrefixOcc . unLoc) ===================================== compiler/Language/Haskell/Syntax/Type.hs ===================================== @@ -393,17 +393,15 @@ data HsForAllTelescope pass } | XHsForAllTelescope !(XXHsForAllTelescope pass) --- A type for interleaved GADT foralls and prefixes, inspired by HsArg --- --- `HsGadtPar` is only usefull for pretty-printing/exact-printing for recovering --- parenthisis interleaved with foralls. +-- | A type for interleaved GADT foralls and parentheses, inspired by HsArg. -- -- Here's an example: -- -- data D where --- MkD :: forall a b. ( forall c. forall d. ( forall. ... --- ↑ ↑ ↑ ↑ ↑ ↑ --- 1 2 3 4 5 6 +-- MkD :: forall x y. -- these go to the `con_outer_bndrs` field +-- forall a b. ( forall c. forall d. ( forall. ... +-- ↑ ↑ ↑ ↑ ↑ ↑ +-- 1 2 3 4 5 6 -- -- That would correspond to a list -- @@ -414,12 +412,15 @@ data HsForAllTelescope pass -- 5 → , HsGadtPar -- 6 → , HsGadtForAll -- , ...] --- --- We can always recover parenthisis structure because they must close after --- return type. data HsGadtArg pass = HsGadtForAll !(XGadtForAll pass) (HsForAllTelescope pass) | HsGadtPar !(XGadtPar pass) + -- ^ `HsGadtPar` is only usefull for pretty-printing/exact-printing for recovering + -- parenthisis interleaved with foralls. + -- + -- This approach differs from `HsPar`, which wraps the inner expression as if + -- surrounding it with parentheses. We can ditch the `HsPar` approach because + -- we know that all parentheses will be closed after the return type. | XHsGadtArg !(XXGadtArg pass) type LHsGadtArg pass = XRec pass (HsGadtArg pass) ===================================== docs/users_guide/exts/gadt_syntax.rst ===================================== @@ -201,12 +201,12 @@ syntactically allowed. Some further various observations about this grammar: something like ``MkS :: Int -> (forall a. a) -> S`` is allowed, since parentheses separate the ``forall`` from the ``->``.) -- Furthermore, GADT constructors do not permit outermost parentheses that - surround the ``foralls`` or ``opt_ctxt``, if at least one of them are - used. For example, ``MkU :: (forall a. a -> U)`` would be rejected, since - it would treat the ``forall`` as being nested. +- GADT constructors permit outermost parentheses that surround the ``foralls`` + or ``opt_ctxt``, as well as interleaved parentheses between multiple + ``foralls``. For example, ``MkU :: (forall a. a -> U)`` is accepted, as is + ``MkW :: forall a. (forall b. a -> b -> W)``. - Note that it is acceptable to use parentheses in a ``prefix_gadt_body``. + Note that it is also acceptable to use parentheses in a ``prefix_gadt_body``. For instance, ``MkV1 :: forall a. (a) -> (V1)`` is acceptable, as is ``MkV2 :: forall a. (a -> V2)``. ===================================== testsuite/tests/printer/T27423c.hs ===================================== @@ -18,6 +18,7 @@ data S a where MkS :: (forall a. S a) MkS2 :: forall. (forall a. S a) MkS3 :: forall. forall a. S a + MkS4 :: forall a. forall. forall b. forall. forall. forall c. S a data U a where MkU :: (Show a => U a) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/52ecaabb7cb818ac8ca7306891fbd622... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/52ecaabb7cb818ac8ca7306891fbd622... You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
participants (1)
-
Andrei Borzenkov (@sand-witch)