Oleg Grenrus pushed to branch wip/keepAlive-th-names-found-in-annotations at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/Rename/Splice.hs
    ... ... @@ -1072,6 +1072,32 @@ a bit hacky.
    1072 1072
     For these chaps (which have Internal Names) we don't want to put
    
    1073 1073
     them in the keep-alive set.
    
    1074 1074
     
    
    1075
    +Note [Keeping things alive referenced by TH.Name from annotations]
    
    1076
    +
    
    1077
    +Consider
    
    1078
    +
    
    1079
    +  {-# ANN module 'f #-}
    
    1080
    +
    
    1081
    +We stage-check annotations as splices, because we are going to run them,
    
    1082
    +and thus similar stage restrictions apply.
    
    1083
    +
    
    1084
    +That however leads for 'f not being persisted. Consider briefly
    
    1085
    +
    
    1086
    +  expr = $(  [| f |] )
    
    1087
    +
    
    1088
    +Here, `f` isn't kept alive by the same mechanism as in
    
    1089
    +Note [Keeping things alive for Template Haskell], as there isn't need for that.
    
    1090
    +Once the splice is evaluated and spliced, compiler will see
    
    1091
    +
    
    1092
    +  expr = f
    
    1093
    +
    
    1094
    +in other words, there will be explicit use of `f`.
    
    1095
    +
    
    1096
    +Returning back to the ANN example: once the annotation is run,
    
    1097
    +we previously had an opaque Serialised blob. There might be a TH Name inside,
    
    1098
    +but GHC won't know about it. To work around that we not only serialise
    
    1099
    +the annotation value, but also traverse it to extract all TH Names.
    
    1100
    +
    
    1075 1101
     Note [Quoting names]
    
    1076 1102
     ~~~~~~~~~~~~~~~~~~~~
    
    1077 1103
     A quoted name 'n is a bit like a quoted expression [| n |], except that we
    

  • compiler/GHC/Tc/Gen/Splice.hs
    ... ... @@ -166,14 +166,16 @@ import qualified Data.ByteString.Lazy as LB
    166 166
     import Data.Dynamic  ( fromDynamic, toDyn )
    
    167 167
     import qualified Data.IntMap as IntMap
    
    168 168
     import qualified Data.Map as Map
    
    169
    -import Data.Typeable ( typeOf, Typeable, TypeRep, typeRep )
    
    170
    -import Data.Data (Data)
    
    169
    +import Data.Typeable ( typeOf, Typeable, TypeRep, typeRep, cast )
    
    170
    +import Data.Data (Data, gmapQ)
    
    171 171
     import Data.Proxy    ( Proxy (..) )
    
    172 172
     import Data.IORef
    
    173 173
     import GHC.Parser.HaddockLex (lexHsDoc)
    
    174 174
     import GHC.Parser (parseIdentifier)
    
    175 175
     import GHC.Rename.Doc (rnHsDoc)
    
    176 176
     
    
    177
    +import Debug.Trace
    
    178
    +
    
    177 179
     {-
    
    178 180
     Note [Template Haskell state diagram]
    
    179 181
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -668,14 +670,12 @@ Example:
    668 670
     -}
    
    669 671
     
    
    670 672
     -- None of these functions add constraints to the LIE
    
    671
    -
    
    672
    -tcTypedBracket    :: HsExpr GhcRn -> LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    673
    -tcUntypedBracket  :: HsExpr GhcRn -> HsQuote GhcRn -> [PendingRnSplice] -> ExpRhoType
    
    674
    -                  -> TcM (HsExpr GhcTc)
    
    675
    -tcTypedSplice     :: HsTypedSpliceResult -> HsTypedSplice GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    676
    -
    
    677
    -getUntypedSpliceBody :: HsUntypedSpliceResult (HsExpr GhcRn) -> TcM (HsExpr GhcRn)
    
    678
    -runAnnotation        :: CoreAnnTarget -> LHsExpr GhcRn -> TcM Annotation
    
    673
    +--
    
    674
    +-- * tcTypedBracket
    
    675
    +-- * tcUntypedBracket
    
    676
    +-- * tcTypedSplice
    
    677
    +-- * getUntypedSpliceBody
    
    678
    +-- * runAnnotation
    
    679 679
     
    
    680 680
     {-
    
    681 681
     ************************************************************************
    
    ... ... @@ -686,6 +686,7 @@ runAnnotation :: CoreAnnTarget -> LHsExpr GhcRn -> TcM Annotation
    686 686
     -}
    
    687 687
     
    
    688 688
     -- See Note [How brackets and nested splices are handled]
    
    689
    +tcTypedBracket :: HsExpr GhcRn -> LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    689 690
     tcTypedBracket rn_expr expr res_ty
    
    690 691
       = addErrCtxt (TypedTHBracketCtxt expr) $
    
    691 692
         do { cur_lvl <- getThLevel
    
    ... ... @@ -728,6 +729,7 @@ tcTypedBracket rn_expr expr res_ty
    728 729
                            meta_ty res_ty }
    
    729 730
     
    
    730 731
     -- See Note [Typechecking Overloaded Quotes]
    
    732
    +tcUntypedBracket :: HsExpr GhcRn -> HsQuote GhcRn -> [PendingRnSplice] -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    731 733
     tcUntypedBracket rn_expr brack ps res_ty
    
    732 734
       = do { traceTc "tc_bracket untyped" (ppr brack $$ ppr ps)
    
    733 735
     
    
    ... ... @@ -929,6 +931,7 @@ tcCodeTy m_ty exp_ty
    929 931
     -- getUntypedSpliceBody: the renamer has expanded the splice.
    
    930 932
     -- Just run the finalizers that it produced, and return
    
    931 933
     -- the renamed expression
    
    934
    +getUntypedSpliceBody :: HsUntypedSpliceResult (HsExpr GhcRn) -> TcM (HsExpr GhcRn)
    
    932 935
     getUntypedSpliceBody (HsUntypedSpliceTop { utsplice_result_finalizers = mod_finalizers
    
    933 936
                                              , utsplice_result = rn_expr })
    
    934 937
       = do { addModFinalizersWithLclEnv mod_finalizers
    
    ... ... @@ -936,6 +939,7 @@ getUntypedSpliceBody (HsUntypedSpliceTop { utsplice_result_finalizers = mod_fina
    936 939
     getUntypedSpliceBody (HsUntypedSpliceNested {})
    
    937 940
       = panic "tcTopUntypedSplice: invalid nested splice"
    
    938 941
     
    
    942
    +tcTypedSplice :: HsTypedSpliceResult -> HsTypedSplice GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    939 943
     tcTypedSplice HsTypedSpliceTop ctxt@(HsTypedSpliceExpr _ expr) res_ty
    
    940 944
       = addErrCtxt (TypedSpliceCtxt Nothing ctxt) $
    
    941 945
         setSrcSpan (getLocA expr)    $
    
    ... ... @@ -1082,6 +1086,7 @@ stubNestedSplice = warnPprTrace True "stubNestedSplice" empty $
    1082 1086
     ************************************************************************
    
    1083 1087
     -}
    
    1084 1088
     
    
    1089
    +runAnnotation :: CoreAnnTarget -> LHsExpr GhcRn -> TcM Annotation
    
    1085 1090
     runAnnotation target expr = do
    
    1086 1091
         -- Find the classes we want instances for in order to call toAnnotationWrapper
    
    1087 1092
         loc <- getSrcSpanM
    
    ... ... @@ -1106,17 +1111,32 @@ runAnnotation target expr = do
    1106 1111
                                     specialised_to_annotation_wrapper_expr expr'))
    
    1107 1112
                                     })
    
    1108 1113
     
    
    1114
    +    traceM $ "runAnnotation: " ++ showPprUnsafe zonked_wrapped_expr'
    
    1115
    +
    
    1109 1116
         -- Run the appropriately wrapped expression to get the value of
    
    1110 1117
         -- the annotation and its dictionaries. The return value is of
    
    1111 1118
         -- type AnnotationWrapper by construction, so this conversion is
    
    1112 1119
         -- safe
    
    1113
    -    serialized <- runMetaAW zonked_wrapped_expr'
    
    1120
    +    (names, serialized) <- runMetaAW zonked_wrapped_expr'
    
    1121
    +    -- See Note [Keeping things alive referenced by TH.Name from annotations]
    
    1122
    +    traceM $ "runAnnotation names: " ++ showPprUnsafe names
    
    1123
    +
    
    1124
    +    forM_ names $ \th_name -> do
    
    1125
    +        mb_name <- lookupThName_maybe th_name
    
    1126
    +        traceM $ "runAnnotation found: " ++ showPprUnsafe mb_name
    
    1127
    +        forM_ mb_name keepAlive -- TODO: do we need to do checks, like isExternalName here?
    
    1128
    +
    
    1114 1129
         return Annotation {
    
    1115 1130
                    ann_target = target,
    
    1116 1131
                    ann_value = serialized
    
    1117 1132
                }
    
    1118 1133
     
    
    1119
    -convertAnnotationWrapper :: ForeignHValue -> TcM Serialized
    
    1134
    +extractTHNames :: Data a => a -> [TH.Name]
    
    1135
    +extractTHNames x = case cast x of
    
    1136
    +    Just n -> [n]
    
    1137
    +    Nothing -> concat (gmapQ extractTHNames x)
    
    1138
    +
    
    1139
    +convertAnnotationWrapper :: ForeignHValue -> TcM ([TH.Name], Serialized)
    
    1120 1140
     convertAnnotationWrapper fhv = do
    
    1121 1141
       interp <- tcGetInterp
    
    1122 1142
       case interpInstance interp of
    
    ... ... @@ -1133,8 +1153,7 @@ convertAnnotationWrapper fhv = do
    1133 1153
                    -- annotation are exposed at this point.  This is also why we are
    
    1134 1154
                    -- doing all this stuff inside the context of runMeta: it has the
    
    1135 1155
                    -- facilities to deal with user error in a meta-level expression
    
    1136
    -               rnf serialized `seq` serialized
    
    1137
    -
    
    1156
    +               (extractTHNames value, rnf serialized `seq` serialized)
    
    1138 1157
     #endif
    
    1139 1158
     
    
    1140 1159
     {-
    
    ... ... @@ -1216,7 +1235,7 @@ defaultRunMeta (MetaAW r)
    1216 1235
     
    
    1217 1236
     ----------------
    
    1218 1237
     runMetaAW :: LHsExpr GhcTc         -- Of type AnnotationWrapper
    
    1219
    -          -> TcM Serialized
    
    1238
    +          -> TcM ([TH.Name], Serialized)
    
    1220 1239
     runMetaAW = runMeta metaRequestAW
    
    1221 1240
     
    
    1222 1241
     runMetaE :: LHsExpr GhcTc          -- Of type (Q Exp)
    

  • compiler/GHC/Types/Meta.hs
    ... ... @@ -14,6 +14,7 @@ where
    14 14
     import GHC.Prelude
    
    15 15
     
    
    16 16
     import GHC.Serialized   ( Serialized )
    
    17
    +import qualified GHC.Boot.TH.Syntax as TH
    
    17 18
     
    
    18 19
     import GHC.Hs
    
    19 20
     import GHC.Utils.Outputable
    
    ... ... @@ -26,7 +27,7 @@ data MetaRequest
    26 27
       | MetaP  (LPat GhcPs      -> MetaResult)
    
    27 28
       | MetaT  (LHsType GhcPs   -> MetaResult)
    
    28 29
       | MetaD  ([LHsDecl GhcPs] -> MetaResult)
    
    29
    -  | MetaAW (Serialized     -> MetaResult)
    
    30
    +  | MetaAW (([TH.Name], Serialized) -> MetaResult)
    
    30 31
     
    
    31 32
     -- | data constructors not exported to ensure correct result type
    
    32 33
     data MetaResult
    
    ... ... @@ -34,7 +35,7 @@ data MetaResult
    34 35
       | MetaResP  (LPat GhcPs)
    
    35 36
       | MetaResT  (LHsType GhcPs)
    
    36 37
       | MetaResD  [LHsDecl GhcPs]
    
    37
    -  | MetaResAW Serialized
    
    38
    +  | MetaResAW ([TH.Name], Serialized)
    
    38 39
     
    
    39 40
     instance Outputable MetaResult where
    
    40 41
         ppr (MetaResE e)   = text "MetaResE"  <> braces (ppr e)
    
    ... ... @@ -63,7 +64,7 @@ unMetaResD :: MetaResult -> [LHsDecl GhcPs]
    63 64
     unMetaResD (MetaResD d) = d
    
    64 65
     unMetaResD mr           = pprPanic "unMetaResD" (ppr mr)
    
    65 66
     
    
    66
    -unMetaResAW :: MetaResult -> Serialized
    
    67
    +unMetaResAW :: MetaResult -> ([TH.Name], Serialized)
    
    67 68
     unMetaResAW (MetaResAW aw) = aw
    
    68 69
     unMetaResAW mr             = pprPanic "unMetaResAW" (ppr mr)
    
    69 70
     
    
    ... ... @@ -81,6 +82,6 @@ metaRequestT h = fmap unMetaResT . h (MetaT MetaResT)
    81 82
     metaRequestD :: Functor f => MetaHook f -> LHsExpr GhcTc -> f [LHsDecl GhcPs]
    
    82 83
     metaRequestD h = fmap unMetaResD . h (MetaD MetaResD)
    
    83 84
     
    
    84
    -metaRequestAW :: Functor f => MetaHook f -> LHsExpr GhcTc -> f Serialized
    
    85
    +metaRequestAW :: Functor f => MetaHook f -> LHsExpr GhcTc -> f ([TH.Name], Serialized)
    
    85 86
     metaRequestAW h = fmap unMetaResAW . h (MetaAW MetaResAW)
    
    86 87
     

  • compiler/GHC/Utils/Outputable.hs
    ... ... @@ -167,6 +167,8 @@ import GHC.Show ( showMultiLineString )
    167 167
     import GHC.Utils.Exception
    
    168 168
     import GHC.Exts (oneShot)
    
    169 169
     
    
    170
    +import qualified GHC.Boot.TH.Syntax as TH
    
    171
    +
    
    170 172
     {-
    
    171 173
     ************************************************************************
    
    172 174
     *                                                                      *
    
    ... ... @@ -1094,13 +1096,15 @@ instance Outputable a => Outputable (SCC a) where
    1094 1096
     instance Outputable Serialized where
    
    1095 1097
         ppr (Serialized the_type bytes) = int (length bytes) <+> text "of type" <+> text (show the_type)
    
    1096 1098
     
    
    1099
    +instance Outputable TH.Name where
    
    1100
    +    ppr = text . TH.showName
    
    1101
    +
    
    1097 1102
     instance Outputable Extension where
    
    1098 1103
         ppr = text . show
    
    1099 1104
     
    
    1100 1105
     instance Outputable ModuleName where
    
    1101 1106
       ppr = pprModuleName
    
    1102 1107
     
    
    1103
    -
    
    1104 1108
     pprModuleName :: IsLine doc => ModuleName -> doc
    
    1105 1109
     pprModuleName (ModuleName nm) =
    
    1106 1110
         docWithStyle (ztext (zEncodeFS nm)) (\_ -> ftext nm)
    
    ... ... @@ -1250,6 +1254,7 @@ instance (OutputableP env a) => OutputableP env (Set a) where
    1250 1254
     instance OutputableP env Void where
    
    1251 1255
         pdoc _ = \ case
    
    1252 1256
     
    
    1257
    +
    
    1253 1258
     {-
    
    1254 1259
     ************************************************************************
    
    1255 1260
     *                                                                      *