Apoorv Ingle pushed to branch wip/ani/kill-popErrCtxt at Glasgow Haskell Compiler / GHC
Commits:
-
e95889e1
by Apoorv Ingle at 2025-09-14T22:26:20-05:00
5 changed files:
- compiler/GHC/Tc/Gen/Do.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Types/ErrCtxt.hs
- compiler/GHC/Tc/Types/LclEnv.hs
- compiler/GHC/Tc/Utils/Monad.hs
Changes:
... | ... | @@ -485,11 +485,11 @@ It stores the original statement (with location) and the expanded expression |
485 | 485 | |
486 | 486 | |
487 | 487 | -- | Wrap a located expression with a `PopErrCtxt`
|
488 | -mkPopErrCtxtExpr :: HsExpr GhcRn -> HsExpr GhcRn
|
|
489 | -mkPopErrCtxtExpr a = XExpr (PopErrCtxt a)
|
|
488 | +-- mkPopErrCtxtExpr :: HsExpr GhcRn -> HsExpr GhcRn
|
|
489 | +-- mkPopErrCtxtExpr a = XExpr (PopErrCtxt a)
|
|
490 | 490 | |
491 | 491 | genPopErrCtxtExpr :: LHsExpr GhcRn -> LHsExpr GhcRn
|
492 | -genPopErrCtxtExpr (L loc a) = L loc (mkPopErrCtxtExpr a)
|
|
492 | +genPopErrCtxtExpr x = x
|
|
493 | 493 | |
494 | 494 | mkExpandedPatRn :: Pat GhcRn -> HsExpr GhcRn -> HsExpr GhcRn
|
495 | 495 | mkExpandedPatRn pat e = XExpr (ExpandedThingRn (OrigPat pat) e) |
... | ... | @@ -1109,5 +1109,5 @@ addExprCtxt e thing_inside |
1109 | 1109 | -- f x = _
|
1110 | 1110 | -- when we don't want to say "In the expression: _",
|
1111 | 1111 | -- because it is mentioned in the error message itself
|
1112 | - XExpr (PopErrCtxt _) -> thing_inside -- popErrCtxt shouldn't push ctxt. see typechecking let stmts
|
|
1112 | + XExpr (ExpandedThingRn o _) -> setInGeneratedCode o thing_inside
|
|
1113 | 1113 | _ -> addErrCtxt (ExprCtxt e) thing_inside -- no op in generated code |
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | {-# LANGUAGE UndecidableInstances #-}
|
5 | 5 | |
6 | 6 | module GHC.Tc.Types.ErrCtxt
|
7 | - ( ErrCtxt, ErrCtxtMsg(..)
|
|
7 | + ( ErrCtxt (..), ErrCtxtMsg(..), srcCodeOriginErrCtxMsg
|
|
8 | 8 | , UserSigType(..), FunAppCtxtFunArg(..)
|
9 | 9 | , TyConInstFlavour(..)
|
10 | 10 | )
|
... | ... | @@ -23,7 +23,7 @@ import GHC.Tc.Zonk.Monad ( ZonkM ) |
23 | 23 | |
24 | 24 | import GHC.Types.Basic ( TyConFlavour )
|
25 | 25 | import GHC.Types.Name ( Name )
|
26 | -import GHC.Types.SrcLoc ( SrcSpan )
|
|
26 | +import GHC.Types.SrcLoc ( SrcSpan, unLoc )
|
|
27 | 27 | import GHC.Types.Var ( Id, TyCoVar )
|
28 | 28 | import GHC.Types.Var.Env ( TidyEnv )
|
29 | 29 | |
... | ... | @@ -50,13 +50,18 @@ import qualified Data.List.NonEmpty as NE |
50 | 50 | |
51 | 51 | -- | Additional context to include in an error message, e.g.
|
52 | 52 | -- "In the type signature ...", "In the ambiguity check for ...", etc.
|
53 | -type ErrCtxt = (Bool, TidyEnv -> ZonkM (TidyEnv, ErrCtxtMsg))
|
|
53 | +data ErrCtxt = UserCodeCtxt (Bool, TidyEnv -> ZonkM (TidyEnv, ErrCtxtMsg))
|
|
54 | 54 | -- Monadic so that we have a chance
|
55 | 55 | -- to deal with bound type variables just before error
|
56 | 56 | -- message construction
|
57 | 57 | |
58 | 58 | -- Bool: True <=> this is a landmark context; do not
|
59 | 59 | -- discard it when trimming for display
|
60 | + | GeneratedCodeCtxt SrcCodeOrigin
|
|
61 | + -- The payload is a SrcCodeOrigin because it is used to generate
|
|
62 | + -- 1. The CtOrigin for CtLoc, and
|
|
63 | + -- 2. ErrCtxtMsg in error messages
|
|
64 | + |
|
60 | 65 | |
61 | 66 | --------------------------------------------------------------------------------
|
62 | 67 | -- Error message contexts
|
... | ... | @@ -221,3 +226,9 @@ data ErrCtxtMsg |
221 | 226 | | MergeSignaturesCtxt !UnitState !ModuleName ![InstantiatedModule]
|
222 | 227 | -- | While checking that a module implements a Backpack signature.
|
223 | 228 | | CheckImplementsCtxt !UnitState !Module !InstantiatedModule
|
229 | + |
|
230 | + |
|
231 | +srcCodeOriginErrCtxMsg :: SrcCodeOrigin -> ErrCtxtMsg
|
|
232 | +srcCodeOriginErrCtxMsg (OrigExpr e) = ExprCtxt e
|
|
233 | +srcCodeOriginErrCtxMsg (OrigStmt s f) = StmtErrCtxt (HsDoStmt f) (unLoc s)
|
|
234 | +srcCodeOriginErrCtxMsg (OrigPat p) = PatCtxt p |
... | ... | @@ -28,7 +28,7 @@ module GHC.Tc.Types.LclEnv ( |
28 | 28 | |
29 | 29 | , addLclEnvErrCtxt
|
30 | 30 | |
31 | - , ErrCtxtStack (..)
|
|
31 | + , ErrCtxtStack
|
|
32 | 32 | , ArrowCtxt(..)
|
33 | 33 | , ThBindEnv
|
34 | 34 | , TcTypeEnv
|
... | ... | @@ -109,36 +109,24 @@ This data structure keeps track of two things: |
109 | 109 | |
110 | 110 | |
111 | 111 | -- See Note [Error Context Stack]
|
112 | -data ErrCtxtStack
|
|
113 | - = UserCodeCtxt { lcl_err_ctxt :: [ErrCtxt] } -- ^ Trail of error messages
|
|
114 | - | GeneratedCodeCtxt { src_code_origin :: SrcCodeOrigin -- ^ Original, user written code
|
|
115 | - , lcl_err_ctxt :: [ErrCtxt] } -- ^ Trail of error messages
|
|
112 | +type ErrCtxtStack = [ErrCtxt]
|
|
116 | 113 | |
117 | 114 | -- | Are we in a generated context?
|
118 | 115 | isGeneratedCodeCtxt :: ErrCtxtStack -> Bool
|
119 | -isGeneratedCodeCtxt UserCodeCtxt{} = False
|
|
120 | -isGeneratedCodeCtxt _ = True
|
|
116 | +isGeneratedCodeCtxt (GeneratedCodeCtxt{} : _) = True
|
|
117 | +isGeneratedCodeCtxt _ = False
|
|
121 | 118 | |
122 | 119 | -- | Get the original source code
|
123 | 120 | get_src_code_origin :: ErrCtxtStack -> Maybe SrcCodeOrigin
|
124 | -get_src_code_origin (UserCodeCtxt{}) = Nothing
|
|
125 | - -- we are in user code, so blame the expression in hand
|
|
126 | -get_src_code_origin es = Just $ src_code_origin es
|
|
121 | +get_src_code_origin (GeneratedCodeCtxt es : _) = Just es
|
|
127 | 122 | -- we are in generated code, so extract the original expression
|
128 | - |
|
129 | --- | Modify the error context stack
|
|
130 | --- N.B. If we are in a generated context, any updates to the context stack are ignored.
|
|
131 | --- We want to blame the errors that appear in a generated expression
|
|
132 | --- to the original, user written code
|
|
133 | -modify_err_ctxt_stack :: ([ErrCtxt] -> [ErrCtxt]) -> ErrCtxtStack -> ErrCtxtStack
|
|
134 | -modify_err_ctxt_stack f (UserCodeCtxt e) = UserCodeCtxt (f e)
|
|
135 | -modify_err_ctxt_stack _ c = c -- any updates on the err context in a generated context should be ignored
|
|
136 | - |
|
123 | +get_src_code_origin _ = Nothing
|
|
124 | + -- we are in user code, so blame the expression in hand
|
|
137 | 125 | |
138 | 126 | data TcLclCtxt
|
139 | 127 | = TcLclCtxt {
|
140 | 128 | tcl_loc :: RealSrcSpan, -- Source span
|
141 | - tcl_ctxt :: ErrCtxtStack, -- See Note [Error Context Stack]
|
|
129 | + tcl_err_ctxt :: ErrCtxtStack, -- See Note [Error Context Stack]
|
|
142 | 130 | tcl_tclvl :: TcLevel,
|
143 | 131 | tcl_bndrs :: TcBinderStack, -- Used for reporting relevant bindings,
|
144 | 132 | -- and for tidying type
|
... | ... | @@ -203,25 +191,30 @@ getLclEnvLoc :: TcLclEnv -> RealSrcSpan |
203 | 191 | getLclEnvLoc = tcl_loc . tcl_lcl_ctxt
|
204 | 192 | |
205 | 193 | getLclEnvErrCtxt :: TcLclEnv -> [ErrCtxt]
|
206 | -getLclEnvErrCtxt = lcl_err_ctxt . tcl_ctxt . tcl_lcl_ctxt
|
|
194 | +getLclEnvErrCtxt = tcl_err_ctxt . tcl_lcl_ctxt
|
|
207 | 195 | |
208 | 196 | setLclEnvErrCtxt :: [ErrCtxt] -> TcLclEnv -> TcLclEnv
|
209 | -setLclEnvErrCtxt ctxt = modifyLclCtxt (\env -> env { tcl_ctxt = modify_err_ctxt_stack (\ _ -> ctxt) (tcl_ctxt env) })
|
|
197 | +setLclEnvErrCtxt ctxt = modifyLclCtxt (\env -> env { tcl_err_ctxt = ctxt })
|
|
210 | 198 | |
211 | 199 | addLclEnvErrCtxt :: ErrCtxt -> TcLclEnv -> TcLclEnv
|
212 | -addLclEnvErrCtxt ec = modifyLclCtxt (\env -> env { tcl_ctxt = modify_err_ctxt_stack (\ctxt -> ec : ctxt) (tcl_ctxt env) })
|
|
200 | +addLclEnvErrCtxt (GeneratedCodeCtxt co) = setLclEnvSrcCodeOrigin co
|
|
201 | +addLclEnvErrCtxt ec = modifyLclCtxt (\env -> env { tcl_err_ctxt = ec : (tcl_err_ctxt env) })
|
|
213 | 202 | |
214 | 203 | getLclEnvSrcCodeOrigin :: TcLclEnv -> Maybe SrcCodeOrigin
|
215 | -getLclEnvSrcCodeOrigin = get_src_code_origin . tcl_ctxt . tcl_lcl_ctxt
|
|
204 | +getLclEnvSrcCodeOrigin = get_src_code_origin . tcl_err_ctxt . tcl_lcl_ctxt
|
|
216 | 205 | |
217 | 206 | setLclEnvSrcCodeOrigin :: SrcCodeOrigin -> TcLclEnv -> TcLclEnv
|
218 | 207 | setLclEnvSrcCodeOrigin o = modifyLclCtxt (setLclCtxtSrcCodeOrigin o)
|
219 | 208 | |
220 | 209 | setLclCtxtSrcCodeOrigin :: SrcCodeOrigin -> TcLclCtxt -> TcLclCtxt
|
221 | -setLclCtxtSrcCodeOrigin o ctxt = ctxt { tcl_ctxt = GeneratedCodeCtxt o (lcl_err_ctxt $ tcl_ctxt ctxt) }
|
|
210 | +setLclCtxtSrcCodeOrigin o lclCtxt
|
|
211 | + | (GeneratedCodeCtxt _ : ec) <- tcl_err_ctxt lclCtxt
|
|
212 | + = lclCtxt { tcl_err_ctxt = GeneratedCodeCtxt o : ec }
|
|
213 | + | otherwise
|
|
214 | + = lclCtxt { tcl_err_ctxt = GeneratedCodeCtxt o : tcl_err_ctxt lclCtxt }
|
|
222 | 215 | |
223 | 216 | lclCtxtInGeneratedCode :: TcLclCtxt -> Bool
|
224 | -lclCtxtInGeneratedCode = isGeneratedCodeCtxt . tcl_ctxt
|
|
217 | +lclCtxtInGeneratedCode = isGeneratedCodeCtxt . tcl_err_ctxt
|
|
225 | 218 | |
226 | 219 | lclEnvInGeneratedCode :: TcLclEnv -> Bool
|
227 | 220 | lclEnvInGeneratedCode = lclCtxtInGeneratedCode . tcl_lcl_ctxt
|
... | ... | @@ -168,6 +168,7 @@ import GHC.Tc.Types -- Re-export all |
168 | 168 | import GHC.Tc.Types.Constraint
|
169 | 169 | import GHC.Tc.Types.CtLoc
|
170 | 170 | import GHC.Tc.Types.Evidence
|
171 | +import GHC.Tc.Types.ErrCtxt
|
|
171 | 172 | import GHC.Tc.Types.LclEnv
|
172 | 173 | import GHC.Tc.Types.Origin
|
173 | 174 | import GHC.Tc.Types.TcRef
|
... | ... | @@ -401,7 +402,7 @@ initTcWithGbl hsc_env gbl_env loc do_this |
401 | 402 | tcl_lcl_ctxt = TcLclCtxt {
|
402 | 403 | tcl_loc = loc,
|
403 | 404 | -- tcl_loc should be over-ridden very soon!
|
404 | - tcl_ctxt = UserCodeCtxt [],
|
|
405 | + tcl_err_ctxt = [],
|
|
405 | 406 | tcl_rdr = emptyLocalRdrEnv,
|
406 | 407 | tcl_th_ctxt = topLevel,
|
407 | 408 | tcl_th_bndrs = emptyNameEnv,
|
... | ... | @@ -983,9 +984,7 @@ inGeneratedCode = lclEnvInGeneratedCode <$> getLclEnv |
983 | 984 | setSrcSpan :: SrcSpan -> TcRn a -> TcRn a
|
984 | 985 | -- See Note [Error contexts in generated code]
|
985 | 986 | setSrcSpan (RealSrcSpan loc _) thing_inside
|
986 | - = updLclCtxt (\env -> env { tcl_loc = loc
|
|
987 | - , tcl_ctxt = UserCodeCtxt (lcl_err_ctxt $ tcl_ctxt env)})
|
|
988 | - thing_inside
|
|
987 | + = updLclCtxt (\env -> env { tcl_loc = loc }) thing_inside
|
|
989 | 988 | |
990 | 989 | setSrcSpan (UnhelpfulSpan _) thing_inside
|
991 | 990 | = thing_inside
|
... | ... | @@ -1252,7 +1251,7 @@ addErrCtxt msg = addErrCtxtM (\env -> return (env, msg)) |
1252 | 1251 | -- See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr
|
1253 | 1252 | addErrCtxtM :: (TidyEnv -> ZonkM (TidyEnv, ErrCtxtMsg)) -> TcM a -> TcM a
|
1254 | 1253 | {-# INLINE addErrCtxtM #-} -- Note [Inlining addErrCtxt]
|
1255 | -addErrCtxtM ctxt = pushCtxt (False, ctxt)
|
|
1254 | +addErrCtxtM ctxt = pushCtxt (UserCodeCtxt (False, ctxt))
|
|
1256 | 1255 | |
1257 | 1256 | -- | Add a fixed landmark message to the error context. A landmark
|
1258 | 1257 | -- message is always sure to be reported, even if there is a lot of
|
... | ... | @@ -1266,7 +1265,7 @@ addLandmarkErrCtxt msg = addLandmarkErrCtxtM (\env -> return (env, msg)) |
1266 | 1265 | -- and tidying.
|
1267 | 1266 | addLandmarkErrCtxtM :: (TidyEnv -> ZonkM (TidyEnv, ErrCtxtMsg)) -> TcM a -> TcM a
|
1268 | 1267 | {-# INLINE addLandmarkErrCtxtM #-} -- Note [Inlining addErrCtxt]
|
1269 | -addLandmarkErrCtxtM ctxt = pushCtxt (True, ctxt)
|
|
1268 | +addLandmarkErrCtxtM ctxt = pushCtxt (UserCodeCtxt (True, ctxt))
|
|
1270 | 1269 | |
1271 | 1270 | -- | NB. no op in generated code
|
1272 | 1271 | -- See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr
|
... | ... | @@ -1277,9 +1276,7 @@ pushCtxt ctxt = updLclEnv (updCtxt ctxt) |
1277 | 1276 | updCtxt :: ErrCtxt -> TcLclEnv -> TcLclEnv
|
1278 | 1277 | -- Do not update the context if we are in generated code
|
1279 | 1278 | -- See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr
|
1280 | -updCtxt ctxt env
|
|
1281 | - | lclEnvInGeneratedCode env = env
|
|
1282 | - | otherwise = addLclEnvErrCtxt ctxt env
|
|
1279 | +updCtxt ctxt env = addLclEnvErrCtxt ctxt env
|
|
1283 | 1280 | |
1284 | 1281 | popErrCtxt :: TcM a -> TcM a
|
1285 | 1282 | popErrCtxt thing_inside = updLclEnv (\env -> setLclEnvErrCtxt (pop $ getLclEnvErrCtxt env) env) $
|
... | ... | @@ -1740,7 +1737,7 @@ mkErrCtxt env ctxts |
1740 | 1737 | where
|
1741 | 1738 | go :: Bool -> Int -> TidyEnv -> [ErrCtxt] -> TcM [ErrCtxtMsg]
|
1742 | 1739 | go _ _ _ [] = return []
|
1743 | - go dbg n env ((is_landmark, ctxt) : ctxts)
|
|
1740 | + go dbg n env (UserCodeCtxt (is_landmark, ctxt) : ctxts)
|
|
1744 | 1741 | | is_landmark || n < mAX_CONTEXTS -- Too verbose || dbg
|
1745 | 1742 | = do { (env', msg) <- liftZonkM $ ctxt env
|
1746 | 1743 | ; let n' = if is_landmark then n else n+1
|
... | ... | @@ -1748,6 +1745,13 @@ mkErrCtxt env ctxts |
1748 | 1745 | ; return (msg : rest) }
|
1749 | 1746 | | otherwise
|
1750 | 1747 | = go dbg n env ctxts
|
1748 | + go dbg n env (GeneratedCodeCtxt co : ctxts)
|
|
1749 | + | n < mAX_CONTEXTS -- Too verbose || dbg
|
|
1750 | + = do { let msg = srcCodeOriginErrCtxMsg co
|
|
1751 | + ; rest <- go dbg (n+1) env ctxts
|
|
1752 | + ; return (msg : rest) }
|
|
1753 | + | otherwise
|
|
1754 | + = go dbg n env ctxts
|
|
1751 | 1755 | |
1752 | 1756 | |
1753 | 1757 | mAX_CONTEXTS :: Int -- No more than this number of non-landmark contexts
|