Apoorv Ingle pushed to branch wip/ani/T27156 at Glasgow Haskell Compiler / GHC
Commits:
-
e691e401
by Apoorv Ingle at 2026-11-02T20:24:08-06:00
8 changed files:
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Tc/Gen/Expand.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Types/LclEnv.hs
- compiler/GHC/Tc/Utils/Monad.hs
- testsuite/tests/th/T18102b.stdout
Changes:
| ... | ... | @@ -57,6 +57,7 @@ import GHC.Core.Type |
| 57 | 57 | import GHC.Builtin.WiredIn.Types (mkTupleStr)
|
| 58 | 58 | import GHC.Tc.Utils.TcType (TcType)
|
| 59 | 59 | import {-# SOURCE #-} GHC.Tc.Types.LclEnv (TcLclEnv)
|
| 60 | +import GHC.Unit.Module.Name ( ModuleName )
|
|
| 60 | 61 | |
| 61 | 62 | import GHCi.RemoteTypes ( ForeignRef )
|
| 62 | 63 | import qualified GHC.Boot.TH.Monad as TH (Q)
|
| ... | ... | @@ -684,7 +685,7 @@ data XXExprGhcRn |
| 684 | 685 | | HsRecSelRn (FieldOcc GhcRn) -- ^ Variable pointing to record selector
|
| 685 | 686 | -- See Note [Non-overloaded record field selectors] and
|
| 686 | 687 | -- Note [Record selectors in the AST]
|
| 687 | - | ReSynBindsRn HsModuleName (HsExpr GhcRn)
|
|
| 688 | + | ReSynBindsRn ModuleName (HsExpr GhcRn)
|
|
| 688 | 689 | |
| 689 | 690 | |
| 690 | 691 | data XXExprGhcTc
|
| ... | ... | @@ -2616,14 +2616,14 @@ repDoE = repDoBlock doEOcc |
| 2616 | 2616 | repMDoE :: Maybe HsModuleName -> Core [(M TH.Stmt)] -> MetaM (Core (M TH.Exp))
|
| 2617 | 2617 | repMDoE = repDoBlock mdoEOcc
|
| 2618 | 2618 | |
| 2619 | -repReSynBindsE :: HsModuleName -> Core (M TH.Exp) -> MetaM (Core (M TH.Exp))
|
|
| 2620 | -repReSynBindsE m (MkC e) = do
|
|
| 2619 | +repReSynBindsE :: ModuleName -> Core (M TH.Exp) -> MetaM (Core (M TH.Exp))
|
|
| 2620 | +repReSynBindsE mod (MkC e) = do
|
|
| 2621 | 2621 | MkC coreModName <- coreModNameM
|
| 2622 | 2622 | krep2 resynbindEOcc [coreModName, e]
|
| 2623 | 2623 | where
|
| 2624 | 2624 | coreModNameM :: MetaM (Core TH.ModName)
|
| 2625 | 2625 | coreModNameM = do
|
| 2626 | - MkC s <- lift $ coreStringLit (moduleNameFS (hsModuleName m))
|
|
| 2626 | + MkC s <- lift $ coreStringLit (moduleNameFS mod)
|
|
| 2627 | 2627 | rep2_nw mkModNameOcc [s]
|
| 2628 | 2628 | |
| 2629 | 2629 | repDoBlock :: KnownOcc -> Maybe HsModuleName -> Core [(M TH.Stmt)] -> MetaM (Core (M TH.Exp))
|
| ... | ... | @@ -47,7 +47,7 @@ import GHC.Builtin.KnownKeys |
| 47 | 47 | import GHC.Builtin.KnownOccs
|
| 48 | 48 | import GHC.Builtin.WiredIn.Types ( nilDataConName, oneDataConName )
|
| 49 | 49 | |
| 50 | -import GHC.Unit.Module ( isInteractiveModule )
|
|
| 50 | +import GHC.Unit.Module ( isInteractiveModule, hsModuleName )
|
|
| 51 | 51 | |
| 52 | 52 | import GHC.Types.Basic (TypeOrKind (TypeLevel))
|
| 53 | 53 | import GHC.Types.FieldLabel
|
| ... | ... | @@ -610,7 +610,7 @@ rnExpr (HsFunArr _ mult arg res) |
| 610 | 610 | rnExpr (XExpr (ReSynBindsPs m e))
|
| 611 | 611 | = do { traceRn "XExpr ReSynBinds" (text "module:" <+> ppr m)
|
| 612 | 612 | ; (e', fvs) <- rnExpr e
|
| 613 | - ; return (XExpr (ReSynBindsRn m e'), fvs)
|
|
| 613 | + ; return (XExpr (ReSynBindsRn (hsModuleName m) e'), fvs)
|
|
| 614 | 614 | }
|
| 615 | 615 | |
| 616 | 616 | {-
|
| ... | ... | @@ -25,12 +25,14 @@ import GHC.Types.SourceText ( SourceText(..) ) |
| 25 | 25 | import GHC.Builtin.KnownOccs
|
| 26 | 26 | import GHC.Builtin.WiredIn.Ids ( leftSectionName, rightSectionName )
|
| 27 | 27 | import GHC.Rename.Utils
|
| 28 | +import GHC.Rename.Env ( lookupOccRnNone )
|
|
| 28 | 29 | |
| 29 | 30 | import GHC.Utils.Panic
|
| 30 | 31 | import GHC.Utils.Outputable
|
| 31 | 32 | |
| 32 | 33 | import qualified Data.List.NonEmpty as NE ( map, head, (<|) )
|
| 33 | 34 | import Data.List.NonEmpty ( NonEmpty(..), init, last, tail )
|
| 35 | +import Data.Maybe ( isJust )
|
|
| 34 | 36 | |
| 35 | 37 | import qualified GHC.LanguageExtensions as LangExt
|
| 36 | 38 | import GHC.Builtin.KnownKeys (getFieldClassOpOcc)
|
| ... | ... | @@ -162,10 +164,22 @@ tcExpand e@(OpApp _ arg1 op arg2) |
| 162 | 164 | |
| 163 | 165 | -- NoRebindable <=> rebindable is turned off
|
| 164 | 166 | -- so we typecheck the HsIf in tcExprNoExpand
|
| 165 | -tcExpand (HsIf NoRebindable _ _ _ )
|
|
| 166 | - = return Nothing
|
|
| 167 | +tcExpand e@(HsIf NoRebindable p b1 b2 )
|
|
| 168 | + = do { isRebindableOn <- getThRebindableSyntax
|
|
| 169 | + -- Check if we are actually expanding a template haskell generated spliced-in expression
|
|
| 170 | + -- and the original expression was typed in a rebindable context
|
|
| 171 | + ; if isJust isRebindableOn
|
|
| 172 | + then do
|
|
| 173 | + { ifThenElseName <- lookupOccRnNone (mkVarUnqual (fsLit "ifThenElse"))
|
|
| 174 | + -- This ought to pass as ifThenElse would be added into the enviornment
|
|
| 175 | + -- by the setThRebindableSyntax call below
|
|
| 176 | + ; return $ Just $
|
|
| 177 | + HSE { hse_ctxt = ExprCtxt e
|
|
| 178 | + , hse_exp = wrapGenSpan $ genHsApps ifThenElseName [p, b1, b2] }
|
|
| 179 | + }
|
|
| 180 | + else return Nothing }
|
|
| 167 | 181 | tcExpand e@(HsIf (Rebindable rs_table) p b1 b2)
|
| 168 | - | Just ifThenElseName <- lookup (rdrNameOcc $ mkVarUnqual (fsLit "ifThenElse")) rs_table
|
|
| 182 | + | Just ifThenElseName <- lookup (rdrNameOcc $ mkVarUnqual (fsLit "ifThenElse")) rs_table
|
|
| 169 | 183 | = return $ Just $
|
| 170 | 184 | HSE { hse_ctxt = ExprCtxt e
|
| 171 | 185 | , hse_exp = wrapGenSpan $ genHsApps ifThenElseName [p, b1, b2]
|
| ... | ... | @@ -288,11 +302,13 @@ tcExpand e@(HsUntypedSplice splice_res _) |
| 288 | 302 | ------------------------
|
| 289 | 303 | -- XExpr
|
| 290 | 304 | |
| 291 | -tcExpand e@(XExpr (ReSynBindsRn _ inner_e))
|
|
| 292 | - = do { -- set environment variable to be in rebindable syntax
|
|
| 293 | - -- add the required rebindable syntax binding names into the environment
|
|
| 294 | - -- try expanding inner_e
|
|
| 295 | - traceTc "tcExpand: ReSynBindsRn" (ppr e)
|
|
| 305 | +tcExpand e@(XExpr (ReSynBindsRn m inner_e))
|
|
| 306 | + = setThRebindableSyntax m $
|
|
| 307 | + -- set environment variable to be in rebindable syntax
|
|
| 308 | + -- add the required rebindable syntax binding names into the environment
|
|
| 309 | + do {
|
|
| 310 | + -- now try expanding inner_e
|
|
| 311 | + ; traceTc "tcExpand: ReSynBindsRn" (ppr e)
|
|
| 296 | 312 | ; e' <- tcExpand inner_e
|
| 297 | 313 | ; let expr = case e' of
|
| 298 | 314 | Just (HSE {hse_exp = expanded_e}) ->
|
| ... | ... | @@ -715,11 +715,11 @@ tcTypedBracket rn_expr expr res_ty |
| 715 | 715 | ; bracket_ty <- mkAppTy m_var <$> tcMetaKnownOccTy expTyConOcc
|
| 716 | 716 | -- wrap the expression with ReSynBinds if rebindable syntax is on in this module
|
| 717 | 717 | ; isRebindableSyntaxOn <- xoptM LangExt.RebindableSyntax
|
| 718 | - ; mname <- moduleName <$> getModule
|
|
| 718 | + ; mod <- moduleName <$> getModule
|
|
| 719 | 719 | ; let expr' = if isRebindableSyntaxOn
|
| 720 | - then case expr of { L loc e -> L loc (XExpr $ ReSynBindsRn (toHsModuleName mname) e) }
|
|
| 720 | + then case expr of { L loc e -> L loc (XExpr $ ReSynBindsRn mod e) }
|
|
| 721 | 721 | else expr
|
| 722 | - ; traceTc "tc_bracket rebindable wrap" (vcat [ppr isRebindableSyntaxOn, ppr mname])
|
|
| 722 | + ; traceTc "tc_bracket rebindable wrap" (vcat [ppr isRebindableSyntaxOn, ppr mod])
|
|
| 723 | 723 | ; let brack_tc = HsBracketTc { hsb_quote = ExpBr noExtField expr', hsb_ty = bracket_ty
|
| 724 | 724 | , hsb_wrap = Just wrapper, hsb_splices = ps' }
|
| 725 | 725 | -- The tc_expr is stored here so that the expression can be used in HIE files.
|
| ... | ... | @@ -12,6 +12,7 @@ module GHC.Tc.Types.LclEnv ( |
| 12 | 12 | , getLclEnvRdrEnv
|
| 13 | 13 | , getLclEnvTcLevel
|
| 14 | 14 | , getLclEnvThLevel
|
| 15 | + , getLclEnvThRebindable
|
|
| 15 | 16 | , setLclEnvTcLevel
|
| 16 | 17 | , setLclEnvLoc
|
| 17 | 18 | , setLclEnvRdrEnv
|
| ... | ... | @@ -19,6 +20,8 @@ module GHC.Tc.Types.LclEnv ( |
| 19 | 20 | , setLclEnvErrCtxt
|
| 20 | 21 | , setLclEnvThLevel
|
| 21 | 22 | , setLclEnvTypeEnv
|
| 23 | + , setLclEnvThRebindable
|
|
| 24 | + , unsetLclEnvThRebindable
|
|
| 22 | 25 | , modifyLclEnvTcLevel
|
| 23 | 26 | |
| 24 | 27 | , setLclEnvHsCtxt
|
| ... | ... | @@ -53,6 +56,8 @@ import GHC.Tc.Types.TcRef |
| 53 | 56 | import GHC.Tc.Types.ErrCtxt
|
| 54 | 57 | import GHC.Tc.Types.Constraint ( WantedConstraints )
|
| 55 | 58 | |
| 59 | +import GHC.Unit.Module.Name ( ModuleName )
|
|
| 60 | + |
|
| 56 | 61 | {-
|
| 57 | 62 | ************************************************************************
|
| 58 | 63 | * *
|
| ... | ... | @@ -111,7 +116,10 @@ data TcLclCtxt |
| 111 | 116 | -- We still need the unsullied global name env so that
|
| 112 | 117 | -- we can look up record field names
|
| 113 | 118 | |
| 114 | - |
|
| 119 | + tcl_th_rs :: Maybe ModuleName, -- Are we type checking a splice
|
|
| 120 | + -- declared with rebindable syntax enabled?
|
|
| 121 | + -- Nothing <=> No rebindable syntax
|
|
| 122 | + -- Just m <=> Rebindable syntax enabled in module m
|
|
| 115 | 123 | tcl_th_ctxt :: ThLevel, -- Template Haskell context
|
| 116 | 124 | tcl_th_bndrs :: ThBindEnv, -- and binder info
|
| 117 | 125 | -- The ThBindEnv records the TH binding level of in-scope Names
|
| ... | ... | @@ -135,6 +143,15 @@ setLclEnvThLevel l = modifyLclCtxt (\env -> env { tcl_th_ctxt = l }) |
| 135 | 143 | getLclEnvThBndrs :: TcLclEnv -> ThBindEnv
|
| 136 | 144 | getLclEnvThBndrs = tcl_th_bndrs . tcl_lcl_ctxt
|
| 137 | 145 | |
| 146 | +getLclEnvThRebindable :: TcLclEnv -> Maybe ModuleName
|
|
| 147 | +getLclEnvThRebindable = tcl_th_rs . tcl_lcl_ctxt
|
|
| 148 | + |
|
| 149 | +setLclEnvThRebindable :: ModuleName -> TcLclEnv -> TcLclEnv
|
|
| 150 | +setLclEnvThRebindable mod = modifyLclCtxt (\env -> env {tcl_th_rs = Just mod} )
|
|
| 151 | + |
|
| 152 | +unsetLclEnvThRebindable :: TcLclEnv -> TcLclEnv
|
|
| 153 | +unsetLclEnvThRebindable = modifyLclCtxt (\env -> env {tcl_th_rs = Nothing} )
|
|
| 154 | + |
|
| 138 | 155 | getLclEnvArrowCtxt :: TcLclEnv -> ArrowCtxt
|
| 139 | 156 | getLclEnvArrowCtxt = tcl_arrow_ctxt . tcl_lcl_ctxt
|
| 140 | 157 |
| ... | ... | @@ -129,6 +129,8 @@ module GHC.Tc.Utils.Monad( |
| 129 | 129 | recordThUse, recordThNeededRuntimeDeps,
|
| 130 | 130 | keepAlive, getThLevel, getCurrentAndBindLevel, setThLevel,
|
| 131 | 131 | addModFinalizersWithLclEnv,
|
| 132 | + setThRebindableSyntax, unsetThRebindableSyntax,
|
|
| 133 | + getThRebindableSyntax,
|
|
| 132 | 134 | |
| 133 | 135 | -- * Safe Haskell context
|
| 134 | 136 | recordUnsafeInfer, finalSafeMode, fixSafeInstances,
|
| ... | ... | @@ -476,6 +478,7 @@ initTcWithGbl hsc_env gbl_env loc do_this |
| 476 | 478 | tcl_in_gen_code = False,
|
| 477 | 479 | tcl_err_ctxt = [],
|
| 478 | 480 | tcl_rdr = emptyLocalRdrEnv,
|
| 481 | + tcl_th_rs = Nothing,
|
|
| 479 | 482 | tcl_th_ctxt = topLevel,
|
| 480 | 483 | tcl_th_bndrs = emptyNameEnv,
|
| 481 | 484 | tcl_arrow_ctxt = NoArrowCtxt,
|
| ... | ... | @@ -2501,6 +2504,17 @@ addModFinalizersWithLclEnv mod_finalizers |
| 2501 | 2504 | updTcRef th_modfinalizers_var $ \fins ->
|
| 2502 | 2505 | (lcl_env, mod_finalizers) : fins
|
| 2503 | 2506 | |
| 2507 | +setThRebindableSyntax :: ModuleName -> TcM a -> TcM a
|
|
| 2508 | +setThRebindableSyntax m = updLclEnv (setLclEnvThRebindable m)
|
|
| 2509 | + |
|
| 2510 | +-- TODO: ANI we probably won't need the unset bit
|
|
| 2511 | +unsetThRebindableSyntax :: TcM a -> TcM a
|
|
| 2512 | +unsetThRebindableSyntax = updLclEnv (unsetLclEnvThRebindable)
|
|
| 2513 | + |
|
| 2514 | +getThRebindableSyntax :: TcM (Maybe ModuleName)
|
|
| 2515 | +getThRebindableSyntax = getLclEnvThRebindable <$> getLclEnv
|
|
| 2516 | + |
|
| 2517 | + |
|
| 2504 | 2518 | {-
|
| 2505 | 2519 | ************************************************************************
|
| 2506 | 2520 | * *
|
| 1 | -10 |
|
| 1 | +25 |