Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC

Commits:

29 changed files:

Changes:

  • .gitlab/ci.sh
    ... ... @@ -1106,7 +1106,7 @@ if [ "${CI_COMMIT_BRANCH:-}" == "master" ] && [ "${CI_PROJECT_PATH:-}" == "ghc/
    1106 1106
       fi
    
    1107 1107
     fi
    
    1108 1108
     if [ -n "${IGNORE_PERF_FAILURES:-}" ]; then
    
    1109
    -  RUNTEST_ARGS=( "${RUNTEST_ARGS[@]:-}" "--ignore-perf-failures=$IGNORE_PERF_FAILURES" )
    
    1109
    +  RUNTEST_ARGS="${RUNTEST_ARGS:-} --ignore-perf-failures=$IGNORE_PERF_FAILURES"
    
    1110 1110
     fi
    
    1111 1111
     
    
    1112 1112
     if [[ -z ${BIGNUM_BACKEND:-} ]]; then BIGNUM_BACKEND=gmp; fi
    

  • changelog.d/27732
    1
    +section: language
    
    2
    +synopsis: Reject ``~``, ``UNPACK`` and multiplicity annotations on ``type data`` fields
    
    3
    +description:
    
    4
    +  ``type data`` declarations (:extension:`TypeData`) now reject any
    
    5
    +  strictness, unpackedness or multiplicity annotation on constructor
    
    6
    +  fields. Previously only ``!`` was rejected.
    
    7
    +mrs: !16563
    
    8
    +issues: #27732

  • compiler/GHC/Hs/Expr.hs
    ... ... @@ -294,7 +294,7 @@ type instance XDo GhcPs = (AnnList, EpaLocation)
    294 294
     type instance XDo            GhcRn = NoExtField
    
    295 295
     type instance XDo            GhcTc = Type
    
    296 296
     
    
    297
    -type instance XExplicitList  GhcPs = AnnList
    
    297
    +type instance XExplicitList  GhcPs = (EpToken "[", EpToken "]")
    
    298 298
     type instance XExplicitList  GhcRn = NoExtField
    
    299 299
     type instance XExplicitList  GhcTc = Type
    
    300 300
     -- GhcPs: ExplicitList includes all source-level
    
    ... ... @@ -1440,7 +1440,7 @@ type instance XCmdArrApp GhcPs = (IsUnicodeSyntax, EpaLocation)
    1440 1440
     type instance XCmdArrApp  GhcRn = NoExtField
    
    1441 1441
     type instance XCmdArrApp  GhcTc = Type
    
    1442 1442
     
    
    1443
    -type instance XCmdArrForm GhcPs = AnnList
    
    1443
    +type instance XCmdArrForm GhcPs = (EpUniToken "(|" "⦇", EpUniToken "|)"  "⦈")
    
    1444 1444
     -- | fixity (filled in by the renamer), for forms that were converted from
    
    1445 1445
     -- OpApp's by the renamer
    
    1446 1446
     type instance XCmdArrForm GhcRn = Maybe Fixity
    

  • compiler/GHC/Hs/Pat.hs
    ... ... @@ -104,7 +104,7 @@ type instance XBangPat GhcPs = EpToken "!"
    104 104
     type instance XBangPat GhcRn = NoExtField
    
    105 105
     type instance XBangPat GhcTc = NoExtField
    
    106 106
     
    
    107
    -type instance XListPat GhcPs = AnnList
    
    107
    +type instance XListPat GhcPs = (EpToken "[", EpToken "]")
    
    108 108
       -- After parsing, ListPat can refer to a built-in Haskell list pattern
    
    109 109
       -- or an overloaded list pattern.
    
    110 110
     type instance XListPat GhcRn = NoExtField
    

  • compiler/GHC/Parser.y
    ... ... @@ -3282,7 +3282,7 @@ aexp2 :: { ECP }
    3282 3282
             -- arrow notation extension
    
    3283 3283
             | '(|' aexp cmdargs '|)'  {% runPV (unECP $2) >>= \ $2 ->
    
    3284 3284
                                           fmap ecpFromCmd $
    
    3285
    -                                      amsA' (sLL $1 $> $ HsCmdArrForm (AnnList (glRM $1) (ListBanana (epUniTok $1) (epUniTok $4)) []) $2 Prefix
    
    3285
    +                                      amsA' (sLL $1 $> $ HsCmdArrForm (epUniTok $1, epUniTok $4) $2 Prefix
    
    3286 3286
                                                                (reverse $3)) }
    
    3287 3287
     
    
    3288 3288
     projection :: { Located (NonEmpty (LocatedAn NoEpAnns (DotFieldOcc GhcPs))) }
    
    ... ... @@ -3414,9 +3414,9 @@ tup_tail :: { forall b. DisambECP b => PV [Either (EpAnn Bool) (LocatedA b)] }
    3414 3414
     -- Never empty.
    
    3415 3415
     list :: { forall b. DisambECP b => SrcSpan -> (EpaLocation, EpaLocation) -> PV (LocatedA b) }
    
    3416 3416
             : texp    { \loc (ao,ac) -> unECP $1 >>= \ $1 ->
    
    3417
    -                            mkHsExplicitListPV loc [$1] (AnnList Nothing (ListSquare (EpTok ao) (EpTok ac)) []) }
    
    3417
    +                            mkHsExplicitListPV loc [$1] (EpTok ao, EpTok ac) }
    
    3418 3418
             | lexps   { \loc (ao,ac) -> $1 >>= \ $1 ->
    
    3419
    -                            mkHsExplicitListPV loc (reverse $1) (AnnList Nothing (ListSquare (EpTok ao) (EpTok ac)) []) }
    
    3419
    +                            mkHsExplicitListPV loc (reverse $1) (EpTok ao, EpTok ac) }
    
    3420 3420
             | texp '..'  { \loc (ao,ac) -> unECP $1 >>= \ $1 ->
    
    3421 3421
                                       amsA' (L loc $ ArithSeq  (AnnArithSeq (EpTok ao) Nothing (epTok $2) (EpTok ac)) Nothing (From $1))
    
    3422 3422
                                           >>= ecpFromExp' }
    

  • compiler/GHC/Parser/Annotation.hs
    ... ... @@ -519,10 +519,8 @@ data AnnList
    519 519
           } deriving (Data,Eq)
    
    520 520
     
    
    521 521
     data AnnListBrackets
    
    522
    -  = ListParens (EpToken "(")         (EpToken ")")
    
    523
    -  | ListBraces (EpToken "{")         (EpToken "}")
    
    522
    +  = ListBraces (EpToken "{")         (EpToken "}")
    
    524 523
       | ListSquare (EpToken "[")         (EpToken "]")
    
    525
    -  | ListBanana (EpUniToken "(|" "⦇") (EpUniToken "|)"  "⦈")
    
    526 524
       | ListNone
    
    527 525
       deriving (Data,Eq)
    
    528 526
     
    
    ... ... @@ -1094,10 +1092,8 @@ instance Outputable AnnList where
    1094 1092
         = text "AnnList" <+> ppr l <+> ppr p <+> ppr s
    
    1095 1093
     
    
    1096 1094
     instance Outputable AnnListBrackets where
    
    1097
    -  ppr (ListParens o c) = text "ListParens" <+> ppr o <+> ppr c
    
    1098 1095
       ppr (ListBraces o c) = text "ListBraces" <+> ppr o <+> ppr c
    
    1099 1096
       ppr (ListSquare o c) = text "ListSquare" <+> ppr o <+> ppr c
    
    1100
    -  ppr (ListBanana o c) = text "ListBanana" <+> ppr o <+> ppr c
    
    1101 1097
       ppr ListNone         = text "ListNone"
    
    1102 1098
     
    
    1103 1099
     instance Outputable AnnCType where
    

  • compiler/GHC/Parser/PostProcess.hs
    ... ... @@ -1827,7 +1827,7 @@ class (b ~ (Body b) GhcPs, AnnoBody b) => DisambECP b where
    1827 1827
       mkHsTySigPV
    
    1828 1828
         :: SrcSpanAnnA -> LocatedA b -> LHsType GhcPs -> TokDcolon -> PV (LocatedA b)
    
    1829 1829
       -- | Disambiguate "[a,b,c]" (list syntax)
    
    1830
    -  mkHsExplicitListPV :: SrcSpan -> [LocatedA b] -> AnnList -> PV (LocatedA b)
    
    1830
    +  mkHsExplicitListPV :: SrcSpan -> [LocatedA b] -> (EpToken "[", EpToken "]") -> PV (LocatedA b)
    
    1831 1831
       -- | Disambiguate "$(...)" and "[quasi|...|]" (TH splices)
    
    1832 1832
       mkHsSplicePV :: Located (HsUntypedSplice GhcPs) -> PV (LocatedA b)
    
    1833 1833
       -- | Disambiguate "f { a = b, ... }" syntax (record construction and record updates)
    

  • compiler/GHC/Rename/Module.hs
    ... ... @@ -71,7 +71,6 @@ import GHC.Data.Graph.Directed ( SCC, flattenSCC, Node(..)
    71 71
                                    , stronglyConnCompFromEdgedVerticesUniq )
    
    72 72
     import GHC.Data.OrdList
    
    73 73
     import qualified GHC.LanguageExtensions as LangExt
    
    74
    -import GHC.Core.DataCon ( isSrcStrict )
    
    75 74
     
    
    76 75
     import Control.Monad
    
    77 76
     import Data.Bifunctor ( first )
    
    ... ... @@ -2116,8 +2115,8 @@ rnDataDefn doc (HsDataDefn { dd_cType = cType, dd_ctxt = context, dd_cons = cond
    2116 2115
           = do {
    
    2117 2116
                ; when (has_labelled_fields condecl) $
    
    2118 2117
                    failWith $ TcRnTypeDataForbids TypeDataForbidsLabelledFields
    
    2119
    -           ; when (has_strictness_flags condecl) $
    
    2120
    -               failWith $ TcRnTypeDataForbids TypeDataForbidsStrictnessAnnotations
    
    2118
    +           ; when (has_field_annotations condecl) $
    
    2119
    +               failWith $ TcRnTypeDataForbids TypeDataForbidsFieldAnnotations
    
    2121 2120
                }
    
    2122 2121
     
    
    2123 2122
         has_labelled_fields (ConDeclGADT { con_g_args = RecConGADT _ _ }) = True
    
    ... ... @@ -2125,13 +2124,19 @@ rnDataDefn doc (HsDataDefn { dd_cType = cType, dd_ctxt = context, dd_cons = cond
    2125 2124
           = not (null (unLoc flds))
    
    2126 2125
         has_labelled_fields _ = False
    
    2127 2126
     
    
    2128
    -    has_strictness_flags condecl
    
    2129
    -      = any isSrcStrict (con_arg_bangs condecl)
    
    2127
    +    has_field_annotations condecl
    
    2128
    +      = not (all unannotated (con_arg_fields condecl))
    
    2129
    +      where
    
    2130
    +        unannotated (CDF { cdf_bang = NoSrcStrict
    
    2131
    +                         , cdf_unpack = NoSrcUnpack
    
    2132
    +                         , cdf_multiplicity = HsModifiedFunArr _ [] (HsStandardArr _) })
    
    2133
    +          = True
    
    2134
    +        unannotated _ = False
    
    2130 2135
     
    
    2131
    -    con_arg_bangs (ConDeclGADT { con_g_args = PrefixConGADT _ args }) = map cdf_bang args
    
    2132
    -    con_arg_bangs (ConDeclH98 { con_args = PrefixCon _ args }) = map cdf_bang args
    
    2133
    -    con_arg_bangs (ConDeclH98 { con_args = InfixCon _ arg1 arg2 }) = [cdf_bang arg1, cdf_bang arg2]
    
    2134
    -    con_arg_bangs _ = []
    
    2136
    +    con_arg_fields (ConDeclGADT { con_g_args = PrefixConGADT _ args }) = args
    
    2137
    +    con_arg_fields (ConDeclH98 { con_args = PrefixCon _ args }) = args
    
    2138
    +    con_arg_fields (ConDeclH98 { con_args = InfixCon _ arg1 arg2 }) = [arg1, arg2]
    
    2139
    +    con_arg_fields _ = []
    
    2135 2140
     
    
    2136 2141
     {-
    
    2137 2142
     Note [Type data declarations]
    
    ... ... @@ -2166,8 +2171,9 @@ preceded by `type`, with the following restrictions:
    2166 2171
     (R2) There are no labelled fields.  Perhaps these could be supported
    
    2167 2172
          using type families, but they are omitted for now.
    
    2168 2173
     
    
    2169
    -(R3) There are no strictness flags, because they don't make sense at
    
    2170
    -     the type level.
    
    2174
    +(R3) There are no strictness, unpackedness or multiplicity annotations
    
    2175
    +     (!, ~, {-# UNPACK #-}, {-# NOUNPACK #-}, %m ->, ⊸), because they
    
    2176
    +     don't make sense at the type level.
    
    2171 2177
     
    
    2172 2178
     (R4) The types of the constructors contain no constraints.
    
    2173 2179
     
    

  • compiler/GHC/Tc/Errors/Types.hs
    ... ... @@ -2866,6 +2866,12 @@ data TcRnMessage where
    2866 2866
            type-data/should_fail/TDRecordsH98
    
    2867 2867
            type-data/should_fail/TDStrictnessGADT
    
    2868 2868
            type-data/should_fail/TDStrictnessH98
    
    2869
    +       type-data/should_fail/T27732a
    
    2870
    +       type-data/should_fail/T27732b
    
    2871
    +       type-data/should_fail/T27732c
    
    2872
    +       type-data/should_fail/T27732d
    
    2873
    +       type-data/should_fail/T27732e
    
    2874
    +       type-data/should_fail/T27732f
    
    2869 2875
       -}
    
    2870 2876
       TcRnTypeDataForbids :: !TypeDataForbids -> TcRnMessage
    
    2871 2877
     
    
    ... ... @@ -4541,15 +4547,15 @@ data ZonkerMessage where
    4541 4547
     data TypeDataForbids
    
    4542 4548
       = TypeDataForbidsDatatypeContexts
    
    4543 4549
       | TypeDataForbidsLabelledFields
    
    4544
    -  | TypeDataForbidsStrictnessAnnotations
    
    4550
    +  | TypeDataForbidsFieldAnnotations
    
    4545 4551
       | TypeDataForbidsDerivingClauses
    
    4546 4552
       deriving Generic
    
    4547 4553
     
    
    4548 4554
     instance Outputable TypeDataForbids where
    
    4549
    -  ppr TypeDataForbidsDatatypeContexts      = text "Data type contexts"
    
    4550
    -  ppr TypeDataForbidsLabelledFields        = text "Labelled fields"
    
    4551
    -  ppr TypeDataForbidsStrictnessAnnotations = text "Strictness flags"
    
    4552
    -  ppr TypeDataForbidsDerivingClauses       = text "Deriving clauses"
    
    4555
    +  ppr TypeDataForbidsDatatypeContexts = text "Data type contexts"
    
    4556
    +  ppr TypeDataForbidsLabelledFields   = text "Labelled fields"
    
    4557
    +  ppr TypeDataForbidsFieldAnnotations = text "Strictness, unpackedness or multiplicity annotations"
    
    4558
    +  ppr TypeDataForbidsDerivingClauses  = text "Deriving clauses"
    
    4553 4559
     
    
    4554 4560
     -- | Specifies which back ends can handle a requested foreign import or export
    
    4555 4561
     type ExpectedBackends = [Backend]
    

  • docs/users_guide/exts/type_data.rst
    ... ... @@ -33,7 +33,8 @@ either an ordinary algebraic data type or a GADT, prefixed with the keyword
    33 33
     ``type``, except that it may not contain
    
    34 34
     a datatype context (even with :extension:`DatatypeContexts`),
    
    35 35
     labelled fields,
    
    36
    -strictness flags, or
    
    36
    +:ref:`strictness <strict-haskell>`, :ref:`unpackedness <unpack-pragma>` or
    
    37
    +:ref:`multiplicity <linear-types>` annotations, or
    
    37 38
     a ``deriving`` clause.
    
    38 39
     
    
    39 40
     The only constraints permitted in the types of constructors are
    

  • testsuite/tests/codeGen/should_run/all.T
    ... ... @@ -258,7 +258,7 @@ test('T24893', normal, compile_and_run, ['-O'])
    258 258
     test('CCallConv', [req_c], compile_and_run, ['CCallConv_c.c'])
    
    259 259
     test('T25364', normal, compile_and_run, [''])
    
    260 260
     test('T26061', normal, compile_and_run, [''])
    
    261
    -test('T26537', normal, compile_and_run, ['-O2 -fregs-graph'])
    
    261
    +test('T26537', compile_timeout_multiplier(1.5), compile_and_run, ['-O2 -fregs-graph'])
    
    262 262
     test('T24016', normal, compile_and_run, ['-O1 -fPIC'])
    
    263 263
     test('T27046',
    
    264 264
          [ req_cmm
    

  • testsuite/tests/ghc-api/T25121_status.stdout
    ... ... @@ -15,7 +15,7 @@ X(FunArr) match = NoExtField
    15 15
     X(ExprWithTySig) match = EpUniToken "::" "\8759"
    
    16 16
     X(UntypedSplice) match = NoExtField
    
    17 17
     X(ExplicitList) mismatch
    
    18
    -  >>> AnnList
    
    18
    +  >>> ((EpToken "["),(EpToken "]"))
    
    19 19
       <<< ((EpToken "'"),(EpToken "["),(EpToken "]"))
    
    20 20
     X(ExplicitTuple) mismatch
    
    21 21
       >>> AnnParen
    

  • testsuite/tests/type-data/should_fail/T27732a.hs
    1
    +{-# LANGUAGE TypeData, LazyFieldAnnotations #-}
    
    2
    +module T27732a where
    
    3
    +
    
    4
    +type data T a = Cons ~a

  • testsuite/tests/type-data/should_fail/T27732a.stderr
    1
    +T27732a.hs:4:17: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    3
    +

  • testsuite/tests/type-data/should_fail/T27732b.hs
    1
    +{-# LANGUAGE TypeData, LazyFieldAnnotations #-}
    
    2
    +module T27732b where
    
    3
    +
    
    4
    +type data T a where
    
    5
    +     Cons :: ~a -> T a

  • testsuite/tests/type-data/should_fail/T27732b.stderr
    1
    +T27732b.hs:5:6: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    3
    +

  • testsuite/tests/type-data/should_fail/T27732c.hs
    1
    +{-# LANGUAGE TypeData #-}
    
    2
    +module T27732c where
    
    3
    +
    
    4
    +type data T a = Cons {-# UNPACK #-} a

  • testsuite/tests/type-data/should_fail/T27732c.stderr
    1
    +T27732c.hs:4:17: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    3
    +

  • testsuite/tests/type-data/should_fail/T27732d.hs
    1
    +{-# LANGUAGE TypeData #-}
    
    2
    +module T27732d where
    
    3
    +
    
    4
    +type data T a = Cons {-# NOUNPACK #-} a

  • testsuite/tests/type-data/should_fail/T27732d.stderr
    1
    +T27732d.hs:4:17: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    3
    +

  • testsuite/tests/type-data/should_fail/T27732e.hs
    1
    +{-# LANGUAGE TypeData, LinearTypes #-}
    
    2
    +module T27732e where
    
    3
    +
    
    4
    +type data T where
    
    5
    +  MkT :: Int %1 -> T

  • testsuite/tests/type-data/should_fail/T27732e.stderr
    1
    +T27732e.hs:5:3: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    3
    +

  • testsuite/tests/type-data/should_fail/T27732f.hs
    1
    +{-# LANGUAGE TypeData, LinearTypes, UnicodeSyntax #-}
    
    2
    +module T27732f where
    
    3
    +
    
    4
    +type data T where
    
    5
    +  MkT :: Int ⊸ T

  • testsuite/tests/type-data/should_fail/T27732f.stderr
    1
    +T27732f.hs:5:3: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    3
    +

  • testsuite/tests/type-data/should_fail/TDStrictnessGADT.stderr
    1
    +TDStrictnessGADT.hs:5:6: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    1 3
     
    2
    -TDStrictnessGADT.hs:5:6: [GHC-67297]
    
    3
    -    Strictness flags are not allowed in type data declarations.

  • testsuite/tests/type-data/should_fail/TDStrictnessH98.stderr
    1
    +TDStrictnessH98.hs:4:17: error: [GHC-67297]
    
    2
    +    Strictness, unpackedness or multiplicity annotations are not allowed in type data declarations.
    
    1 3
     
    2
    -TDStrictnessH98.hs:4:17: [GHC-67297]
    
    3
    -    Strictness flags are not allowed in type data declarations.

  • testsuite/tests/type-data/should_fail/all.T
    ... ... @@ -13,3 +13,9 @@ test('TDStrictnessGADT', normal, compile_fail, [''])
    13 13
     test('TDStrictnessH98', normal, compile_fail, [''])
    
    14 14
     test('TDTagToEnum', normal, compile_fail, [''])
    
    15 15
     test('T22332b', normal, compile_fail, [''])
    
    16
    +test('T27732a', normal, compile_fail, [''])
    
    17
    +test('T27732b', normal, compile_fail, [''])
    
    18
    +test('T27732c', normal, compile_fail, [''])
    
    19
    +test('T27732d', normal, compile_fail, [''])
    
    20
    +test('T27732e', normal, compile_fail, [''])
    
    21
    +test('T27732f', normal, compile_fail, [''])

  • utils/check-exact/ExactPrint.hs
    ... ... @@ -140,9 +140,9 @@ defaultEPState = EPState
    140 140
     
    
    141 141
     -- | The R part of RWS. The environment. Updated via 'local' as we
    
    142 142
     -- enter a new AST element, having a different anchor point.
    
    143
    -data EPOptions m a = EPOptions
    
    144
    -            { epTokenPrint :: String -> m a
    
    145
    -            , epWhitespacePrint :: String -> m a
    
    143
    +data EPOptions m w = EPOptions
    
    144
    +            { epTokenPrint :: String -> m w
    
    145
    +            , epWhitespacePrint :: String -> m w
    
    146 146
                 }
    
    147 147
     
    
    148 148
     -- | Helper to create a 'EPOptions'
    
    ... ... @@ -163,8 +163,7 @@ stringOptions = epOptions return return
    163 163
     deltaOptions :: EPOptions Identity ()
    
    164 164
     deltaOptions = epOptions (\_ -> return ()) (\_ -> return ())
    
    165 165
     
    
    166
    -data EPWriter a = EPWriter
    
    167
    -              { output :: !a }
    
    166
    +data EPWriter w = EPWriter { output :: !w }
    
    168 167
     
    
    169 168
     instance Monoid w => Semigroup (EPWriter w) where
    
    170 169
       (EPWriter a) <> (EPWriter b) = EPWriter (a <> b)
    
    ... ... @@ -239,7 +238,220 @@ setAnchorEpaL (EpAnn _ an _) anc ts cs = EpAnn anc (setTrailing (an {al_anchor =
    239 238
     -- | Key entry point.  Switches to an independent AST element with its
    
    240 239
     -- own annotation, calculating new offsets, etc
    
    241 240
     markAnnotated :: (Monad m, Monoid w, ExactPrint a) => a -> EP w m a
    
    242
    -markAnnotated a = enterAnn (getAnnotationEntry a) a
    
    241
    +markAnnotated a = enterAnn (getAnnotationEntry a) a -- See Note [Exact print main loop]
    
    242
    +
    
    243
    +{-
    
    244
    +Note [Exact print main loop]
    
    245
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    246
    +
    
    247
    +Exact printing is the process of taking the ParsedSource, or some
    
    248
    +subtree from it, and rendering it to a string, which accurately
    
    249
    +reflects the original source that was parsed, except detail of
    
    250
    +whitespace (such as spaces vs tabs) is discarded.
    
    251
    +
    
    252
    +The ParsedSource or fragment from it must implement the ExactPrint
    
    253
    +class, and this file does that, as well as supporting machinery to
    
    254
    +drive the process. The ExactPrint class is described later in this
    
    255
    +note.
    
    256
    +
    
    257
    +The entry point for exact printing is the exactPrint function, defined
    
    258
    +as
    
    259
    +
    
    260
    +  exactPrint :: ExactPrint ast => ast -> String
    
    261
    +  exactPrint ast = snd $ runIdentity (runEP stringOptions (markAnnotated ast))
    
    262
    +
    
    263
    +  type EP w m a = RWST (EPOptions m w) (EPWriter w) EPState m a
    
    264
    +
    
    265
    +  runEP :: (Monad m) => EPOptions m w -> EP w m a -> m (a, w)
    
    266
    +  runEP epReader action = do
    
    267
    +    (ast, w) <- evalRWST action epReader defaultEPState
    
    268
    +    return (ast, output w)
    
    269
    +
    
    270
    +  data EPWriter w = EPWriter { output :: !w }
    
    271
    +
    
    272
    +  data EPOptions m w = EPOptions
    
    273
    +              { epTokenPrint :: String -> m w
    
    274
    +              , epWhitespacePrint :: String -> m w
    
    275
    +              }
    
    276
    +
    
    277
    +This offers some flexibility in how the output is produced, in that
    
    278
    +the EpWriter and EPOptions work together, defining an output type and
    
    279
    +a function to render whitespace and non-whitepace.
    
    280
    +
    
    281
    +In normal operation (via exactPrint) these are simply returning the
    
    282
    +string unchanged and accumulating a larger string. But it has also been
    
    283
    +used to render an HTML version of the source as it prints.
    
    284
    +
    
    285
    +The main reason exact print exists is to make it easier for tool
    
    286
    +writers to manipulate the ParsedSource, and render this back to the
    
    287
    +original source, except for the changed parts. One manipulation is to
    
    288
    +simply take say a FunBind with its signature from one place in the
    
    289
    +code to another. When doing this, the original parsed locations are no
    
    290
    +longer useful when rendering the source back to a string. To enable
    
    291
    +this, we have another entry point, for converting all absolute
    
    292
    +locations to relative ones, using DeltaPos, which captures the line
    
    293
    +and col offset relative to the prior output.
    
    294
    +
    
    295
    +The function to do this is
    
    296
    +
    
    297
    +  makeDeltaAst :: ExactPrint ast => ast -> ast
    
    298
    +  makeDeltaAst ast = fst $ runIdentity (runEP deltaOptions (markAnnotated ast))
    
    299
    +
    
    300
    +The implementation is practically identical for exactPrint and
    
    301
    +makeDeltaAst, they simply return the second or first part of the same
    
    302
    +calculation.
    
    303
    +
    
    304
    +This simplifies the implementation of the required ExactPrint
    
    305
    +implmentations, in that we only need one per ast item, which encodes
    
    306
    +how to print it, and this print process does bookkeeping to keep track
    
    307
    +of what spacing it used when doing the print, so it can return the
    
    308
    +updated item, with the original absolute SrcSpan's converted to
    
    309
    +DeltaPos values instead.
    
    310
    +
    
    311
    +This information is captured in the XRec/Anno instances used in GHC
    
    312
    +Hs, which are mostly LocatedA a, defined as
    
    313
    +
    
    314
    +  GenLocated (EpAnn [TrailingAnn]) a
    
    315
    +
    
    316
    +  data EpAnn ann
    
    317
    +    = EpAnn { entry   :: !EpaLocation
    
    318
    +            , anns     :: !ann
    
    319
    +            , comments :: !EpAnnComments
    
    320
    +            }
    
    321
    +
    
    322
    +  data EpaLocation = EpaSpan !SrcSpan
    
    323
    +                   | EpaDelta !SrcSpan !DeltaPos [LEpaComment]
    
    324
    +
    
    325
    +When parsed, the entry EpaLocation captures an EpaSpan with the parsed
    
    326
    +absolute location. After makeDeltaAst, this instead uses EpaDelta,
    
    327
    +including the original SrcSpan, the relative spaceing as a DeltaPos,
    
    328
    +and any comments that may come before the item, e.g. comments before a
    
    329
    +semicolon.
    
    330
    +
    
    331
    +Both exactPrint and makeDeltaAst call markAnnotated on the item to be
    
    332
    +printed, inside the monad machinery.
    
    333
    +
    
    334
    +  markAnnotated :: (Monad m, Monoid w, ExactPrint a) => a -> EP w m a
    
    335
    +  markAnnotated a = enterAnn (getAnnotationEntry a) a
    
    336
    +
    
    337
    +This makes use of the ExactPrint instance for the ParsedSource and
    
    338
    +for every other part of the ParsedSource as a tree.
    
    339
    +
    
    340
    +  class (Typeable a) => ExactPrint a where
    
    341
    +    getAnnotationEntry :: a -> Entry
    
    342
    +    exact :: (Monad m, Monoid w) => a -> EP w m a
    
    343
    +    setAnnotationAnchor :: a -> EpaLocation -> [TrailingAnn] -> EpAnnComments -> a
    
    344
    +
    
    345
    +- getAnnotationEntry : returns the Entry information, normally derived
    
    346
    +                       directly from the EpAnn in the LocatedA enclosing the item.
    
    347
    +    Entry contains
    
    348
    +    - The location of the first non-comment part of the item to be printed.
    
    349
    +    - Any [TrailingAnn] (semis, commas, etc) to follow the item.
    
    350
    +    - Any comments associated with the item, but not with enclosed items.
    
    351
    +      These comments may also precede or follow the entry location
    
    352
    +    - Some technical flags, relating to flushing remaining comments at the
    
    353
    +      last (topmost) item, and if the anchor can be updated (see below).
    
    354
    +
    
    355
    +- exact : Do the actual printing of the item, having been put in the right
    
    356
    +  place in terms of print location by the main loop, based on a call to
    
    357
    +  getAnnotationEntry for it. This printing normally comprises making nested
    
    358
    +  markAnnotated calls on the nested items in the current one, e.g.
    
    359
    +
    
    360
    +    exact (HsApp an e1 e2) = do
    
    361
    +      e1' <- markAnnotated e1
    
    362
    +      e2' <- markAnnotated e2
    
    363
    +      return (HsApp an e1' e2')
    
    364
    +
    
    365
    +- setAnnotationAnchor : the main loop printing does two things:
    
    366
    +  - produce output, reflecting the items being printed
    
    367
    +  - convert all the locations in the item (each an EpaLocation) from its
    
    368
    +    EpaSpan version to an EpaDelta one, which is independent of absolute
    
    369
    +    location, being the spacing from the previous print output to this
    
    370
    +    entry point
    
    371
    +  To allow these updated locations to be captured, the item implements
    
    372
    +  the setAnnotationAnchor method, which updates the fields of the Entry
    
    373
    +  returned by getAnnotationEntry
    
    374
    +
    
    375
    +You will recall
    
    376
    +
    
    377
    +  markAnnotated a = enterAnn (getAnnotationEntry a) a
    
    378
    +  enterAnn :: (Monad m, Monoid w, ExactPrint a) => Entry -> a -> EP w m a
    
    379
    +
    
    380
    +enterAnn is the part that is repeatedly called via markAnnotated, to
    
    381
    +manage the bookkeeping around printing and calculating the updated
    
    382
    +delta positions.
    
    383
    +
    
    384
    +It manages the printing state, adding the new comments from the Entry,
    
    385
    +positioning the print head to the entry point, takes account of whether
    
    386
    +it is an absolute span or a delta, and prints any comments that must come
    
    387
    +before this location.
    
    388
    +
    
    389
    +At this print location, it calls the `exact` method on the item. This
    
    390
    +is the only place `exact` can be called. Within `exact` implementations
    
    391
    +the `markAnnotated` function should be used instead, to ensure the state
    
    392
    +is managed properly for printing.
    
    393
    +
    
    394
    +Once the item is printed via its `exact` method, which normally
    
    395
    +recurses via `markAnnotated` into any nested items inside it, the
    
    396
    +`enterAnn` function prints any [TrailingAnn] from the entry and any
    
    397
    +trailing comments. It then wraps up by calling
    
    398
    +`setAnnotationAnchor`with the updated (now delta-based) values for the
    
    399
    +Entry
    
    400
    +
    
    401
    +Printing Complicated Items
    
    402
    +~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    403
    +Sometimes we need to print a sub-item which does not map cleanly onto the
    
    404
    +ExactPrint class, usually because there are parts spread through the item
    
    405
    +that need to be managed together while printing.
    
    406
    +
    
    407
    +An example is in
    
    408
    +https://gitlab.haskell.org/ghc/ghc/-/merge_requests/16321, where
    
    409
    +ConDeclGADT needs to print its inner_bindings, but the these in turn
    
    410
    +may have parens, e.g.
    
    411
    +
    
    412
    +  data V a where
    
    413
    +    MkV4 :: forall a. ((forall b. (Show a => a -> (b -> V a))))
    
    414
    +
    
    415
    +Here there are inner bindings for the first forall, the multiple
    
    416
    +parens around the second forall, and the second forall, wrapping the
    
    417
    +inner content within this.
    
    418
    +
    
    419
    +But the inner content `Show a => a -> (b -> V a)` had to be printed "inside"
    
    420
    +the inner_bindings, to correctly close the nested parens.
    
    421
    +
    
    422
    +The approach in !16321 modified `enterAnn`, to pass in alternate versions
    
    423
    +of the `exact` implementation. This works, but it makes an already
    
    424
    +complicated function even more complicated.
    
    425
    +
    
    426
    +An ExactPrint-idiomatic approach is to create a helper data structure
    
    427
    +to represent this nested organisation, and provide ExactPrint
    
    428
    +instances for that.
    
    429
    +
    
    430
    +This is done in
    
    431
    +https://gitlab.haskell.org/ghc/ghc/-/merge_requests/16644, using
    
    432
    +
    
    433
    +  data InnerBindings
    
    434
    +    = InnerMore (LHsGadtTelescope GhcPs) InnerBindings
    
    435
    +    | InnerDone (Maybe (LHsContext GhcPs), HsConDeclGADTDetails GhcPs, LHsType GhcPs)
    
    436
    +
    
    437
    +The key part of the ExactPrint instance for this is
    
    438
    +
    
    439
    +  exact  (InnerMore (L l (HsGadtPar (lp, rp))) xs) = do
    
    440
    +    lp' <- markEpToken lp
    
    441
    +    xs' <- markAnnotated xs
    
    442
    +    rp' <- markEpToken rp
    
    443
    +    return (InnerMore (L l (HsGadtPar (lp',rp'))) xs')
    
    444
    +
    
    445
    +This first prints the opening paren, prints the balance of the cons list, then
    
    446
    +prints the closing paren.
    
    447
    +
    
    448
    +Conversions to and from this structure populate the initial values from
    
    449
    +the ConDeclGADT, and retrieve the updated delta-based values after
    
    450
    +printing.
    
    451
    +
    
    452
    +Another use of this technique involves HsModuleImpDecls.
    
    453
    +
    
    454
    +-}
    
    243 455
     
    
    244 456
     -- | For HsModule, because we do not have a proper SrcSpan, we must
    
    245 457
     -- indicate to flush trailing comments when done.
    
    ... ... @@ -377,6 +589,7 @@ cua NoCanUpdateAnchor _ = return []
    377 589
     -- This is combination of the ghc=exactprint Delta.withAST and
    
    378 590
     -- Print.exactPC functions and effectively does the delta processing
    
    379 591
     -- immediately followed by the print processing.  JIT ghc-exactprint.
    
    592
    +-- See Note [Exact print main loop]
    
    380 593
     enterAnn :: (Monad m, Monoid w, ExactPrint a) => Entry -> a -> EP w m a
    
    381 594
     enterAnn NoEntryVal a = do
    
    382 595
       p <- getPosP
    
    ... ... @@ -764,18 +977,12 @@ markLensBracketsO' :: (Monad m, Monoid w)
    764 977
       => a -> Lens a AnnListBrackets -> EP w m a
    
    765 978
     markLensBracketsO' a l =
    
    766 979
       case view l a of
    
    767
    -    ListParens o c -> do
    
    768
    -      o' <- markEpToken o
    
    769
    -      return (set l (ListParens o' c) a)
    
    770 980
         ListBraces o c -> do
    
    771 981
           o' <- markEpToken o
    
    772 982
           return (set l (ListBraces o' c) a)
    
    773 983
         ListSquare o c -> do
    
    774 984
           o' <- markEpToken o
    
    775 985
           return (set l (ListSquare o' c) a)
    
    776
    -    ListBanana o c -> do
    
    777
    -      o' <- markEpUniToken o
    
    778
    -      return (set l (ListBanana o' c) a)
    
    779 986
         ListNone -> return (set l ListNone a)
    
    780 987
     
    
    781 988
     markLensBracketsC :: (Monad m, Monoid w)
    
    ... ... @@ -786,18 +993,12 @@ markLensBracketsC' :: (Monad m, Monoid w)
    786 993
       => a -> Lens a AnnListBrackets -> EP w m a
    
    787 994
     markLensBracketsC' a l =
    
    788 995
       case view l a of
    
    789
    -    ListParens o c -> do
    
    790
    -      c' <- markEpToken c
    
    791
    -      return (set l (ListParens o c') a)
    
    792 996
         ListBraces o c -> do
    
    793 997
           c' <- markEpToken c
    
    794 998
           return (set l (ListBraces o c') a)
    
    795 999
         ListSquare o c -> do
    
    796 1000
           c' <- markEpToken c
    
    797 1001
           return (set l (ListSquare o c') a)
    
    798
    -    ListBanana o c -> do
    
    799
    -      c' <- markEpUniToken c
    
    800
    -      return (set l (ListBanana o c') a)
    
    801 1002
         ListNone -> return (set l ListNone a)
    
    802 1003
     
    
    803 1004
     -- -------------------------------------
    
    ... ... @@ -2919,13 +3120,13 @@ instance ExactPrint (HsExpr GhcPs) where
    2919 3120
         (an',l',stmts') <- exactDo (an,l) do_or_list_comp stmts
    
    2920 3121
         return (HsDo (an',l') do_or_list_comp stmts')
    
    2921 3122
     
    
    2922
    -  exact (ExplicitList an es) = do
    
    3123
    +  exact (ExplicitList (o,c) es) = do
    
    2923 3124
         debugM $ "ExplicitList start"
    
    2924
    -    an0 <- markLensBracketsO' an lal_brackets
    
    3125
    +    o' <- markEpToken o
    
    2925 3126
         es' <- mapM markAnnotated es
    
    2926
    -    an1 <- markLensBracketsC' an0 lal_brackets
    
    3127
    +    c' <- markEpToken c
    
    2927 3128
         debugM $ "ExplicitList end"
    
    2928
    -    return (ExplicitList an1 es')
    
    3129
    +    return (ExplicitList (o',c') es')
    
    2929 3130
       exact (RecordCon x con_id binds) = do
    
    2930 3131
         con_id' <- markAnnotated con_id
    
    2931 3132
         binds' <- markAnnotated binds
    
    ... ... @@ -3335,8 +3536,8 @@ instance ExactPrint (HsCmd GhcPs) where
    3335 3536
         arr' <- markAnnotated arr
    
    3336 3537
         return (HsCmdArrApp (isU, l') arr' arg' HsHigherOrderApp False)
    
    3337 3538
     
    
    3338
    -  exact (HsCmdArrForm an e fixity cs) = do
    
    3339
    -    an0 <- markLensBracketsO' an lal_brackets
    
    3539
    +  exact (HsCmdArrForm (o,c) e fixity cs) = do
    
    3540
    +    o' <- markEpUniToken o
    
    3340 3541
         (e',cs') <- case (fixity, cs) of
    
    3341 3542
           (Infix, (arg1:argrest)) -> do
    
    3342 3543
             arg1' <- markAnnotated arg1
    
    ... ... @@ -3348,8 +3549,8 @@ instance ExactPrint (HsCmd GhcPs) where
    3348 3549
             cs' <- mapM markAnnotated cs
    
    3349 3550
             return (e', cs')
    
    3350 3551
           (Infix, []) -> error "Not possible"
    
    3351
    -    an1 <- markLensBracketsC' an0 lal_brackets
    
    3352
    -    return (HsCmdArrForm an1 e' fixity cs')
    
    3552
    +    c' <- markEpUniToken c
    
    3553
    +    return (HsCmdArrForm (o',c') e' fixity cs')
    
    3353 3554
     
    
    3354 3555
       exact (HsCmdApp an e1 e2) = do
    
    3355 3556
         e1' <- markAnnotated e1
    
    ... ... @@ -4671,9 +4872,11 @@ instance ExactPrint (Pat GhcPs) where
    4671 4872
         pat' <- markAnnotated pat
    
    4672 4873
         return (BangPat an0 pat')
    
    4673 4874
     
    
    4674
    -  exact (ListPat an pats) = do
    
    4675
    -    (an', pats') <- markAnnList' an (mapM markAnnotated pats)
    
    4676
    -    return (ListPat an' pats')
    
    4875
    +  exact (ListPat (os,cs) pats) = do
    
    4876
    +    os' <- markEpToken os
    
    4877
    +    pats' <- mapM markAnnotated pats
    
    4878
    +    cs' <- markEpToken cs
    
    4879
    +    return (ListPat (os',cs') pats')
    
    4677 4880
     
    
    4678 4881
       exact (TuplePat an pats boxity) = do
    
    4679 4882
         an0 <- markOpeningParen an
    

  • utils/check-exact/Utils.hs
    ... ... @@ -342,10 +342,8 @@ insertTopLevelCppComments (HsModule (XModulePs an lo mdeprec mbDoc) mmn mexports
    342 342
             (xs',rest') = allocPreceding xs rest
    
    343 343
     
    
    344 344
     annListBracketsLocs :: AnnListBrackets -> (EpaLocation,EpaLocation)
    
    345
    -annListBracketsLocs (ListParens o c) = (getEpTokenLoc o,    getEpTokenLoc c)
    
    346 345
     annListBracketsLocs (ListBraces o c) = (getEpTokenLoc o,    getEpTokenLoc c)
    
    347 346
     annListBracketsLocs (ListSquare o c) = (getEpTokenLoc o,    getEpTokenLoc c)
    
    348
    -annListBracketsLocs (ListBanana o c) = (getEpUniTokenLoc o, getEpUniTokenLoc c)
    
    349 347
     annListBracketsLocs ListNone         = (noAnn,              noAnn)
    
    350 348
     
    
    351 349
     data SplitWhere = Before | After