Simon Peyton Jones pushed to branch wip/spj-apporv-Oct24 at Glasgow Haskell Compiler / GHC
Commits:
-
4b99e8e7
by Simon Peyton Jones at 2026-03-21T21:54:07+00:00
14 changed files:
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/CtLoc.hs
- compiler/GHC/Tc/Types/ErrCtxt.hs
- compiler/GHC/Tc/Types/LclEnv.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
Changes:
| ... | ... | @@ -1447,7 +1447,7 @@ mkErrorReport :: CtLocEnv |
| 1447 | 1447 | -- ^ Suggested fixes
|
| 1448 | 1448 | -> TcM (MsgEnvelope TcRnMessage)
|
| 1449 | 1449 | mkErrorReport tcl_env msg mb_ctxt supp hints
|
| 1450 | - = do { mb_context <- traverse (\ ctxt -> mkErrCtxt (cec_tidy ctxt) (ctl_ctxt tcl_env)) mb_ctxt
|
|
| 1450 | + = do { mb_context <- traverse (\ ctxt -> tidyErrCtxt (cec_tidy ctxt) (ctl_ctxt tcl_env)) mb_ctxt
|
|
| 1451 | 1451 | ; unit_state <- hsc_units <$> getTopEnv
|
| 1452 | 1452 | ; hfdc <- getHoleFitDispConfig
|
| 1453 | 1453 | ; let
|
| ... | ... | @@ -7650,7 +7650,7 @@ pprTypeSyntaxName ContextArrowSyntax = "context arrow (=>)" |
| 7650 | 7650 | pprTypeSyntaxName FunctionArrowSyntax = "function type arrow (->)"
|
| 7651 | 7651 | |
| 7652 | 7652 | --------------------------------------------------------------------------------
|
| 7653 | --- ErrCtxt
|
|
| 7653 | +-- HsCtxt
|
|
| 7654 | 7654 | |
| 7655 | 7655 | pprTyConInstFlavour :: TyConInstFlavour -> SDoc
|
| 7656 | 7656 | pprTyConInstFlavour
|
| ... | ... | @@ -957,8 +957,8 @@ addArgCtxt arg_no (app_head, app_head_lspan) (L arg_loc arg) thing_inside |
| 957 | 957 | , ppr arg
|
| 958 | 958 | , ppr arg_no])
|
| 959 | 959 | ; setSrcSpanA arg_loc $
|
| 960 | - addErrCtxt (FunAppCtxt (FunAppCtxtExpr app_head arg) arg_no) $
|
|
| 961 | - thing_inside
|
|
| 960 | + addErrCtxt (FunAppCtxt (FunAppCtxtExpr app_head arg) arg_no) $
|
|
| 961 | + thing_inside
|
|
| 962 | 962 | }
|
| 963 | 963 | | otherwise
|
| 964 | 964 | = do { traceTc "addArgCtxt" (vcat [text "generated Head"
|
| ... | ... | @@ -966,8 +966,9 @@ addArgCtxt arg_no (app_head, app_head_lspan) (L arg_loc arg) thing_inside |
| 966 | 966 | , ppr app_head_lspan
|
| 967 | 967 | , ppr arg_loc
|
| 968 | 968 | , ppr arg])
|
| 969 | - ; addLExprCtxt (locA arg_loc) arg $
|
|
| 970 | - thing_inside
|
|
| 969 | + ; setSrcSpanA arg_loc $
|
|
| 970 | + addExprCtxt arg $
|
|
| 971 | + thing_inside
|
|
| 971 | 972 | }
|
| 972 | 973 | |
| 973 | 974 | |
| ... | ... | @@ -2012,17 +2013,21 @@ quickLookArg1 pos app_lspan (fun, fun_lspan) larg@(L _ arg) sc_arg_ty@(Scaled _ |
| 2012 | 2013 | , eaql_res_rho = app_res_rho }) }}}
|
| 2013 | 2014 | |
| 2014 | 2015 | |
| 2015 | -mk_origin :: SrcSpan -- SrcSpan of the argument
|
|
| 2016 | +mk_origin :: SrcSpan -- SrcSpan of the function
|
|
| 2016 | 2017 | -> HsExpr GhcRn -- The head of the expression application chain
|
| 2017 | 2018 | -> TcM CtOrigin
|
| 2018 | 2019 | mk_origin fun_lspan rn_fun
|
| 2019 | 2020 | | not (isGeneratedSrcSpan fun_lspan)
|
| 2020 | 2021 | = return $ exprCtOrigin rn_fun
|
| 2021 | - | otherwise -- if the location is generated,
|
|
| 2022 | - -- the best we can do is to approximate by looking on top of the error message stack
|
|
| 2023 | - = do { code_orig <- getHsCtxt
|
|
| 2024 | - ; traceTc "mk_origin" (pprHsCtxt code_orig)
|
|
| 2025 | - ; return $ hsCtxtCtOrigin code_orig
|
|
| 2022 | + |
|
| 2023 | + | otherwise -- If the location is generated, the best we can do is to
|
|
| 2024 | + -- approximate by looking on top of the error message stack
|
|
| 2025 | + = do { err_ctxt_stack <- getErrCtxt
|
|
| 2026 | + ; let hs_ctxt = case err_ctxt_stack of
|
|
| 2027 | + (c:_) -> c
|
|
| 2028 | + [] -> pprPanic "mk_origin" (ppr rn_fun)
|
|
| 2029 | + ; traceTc "mk_origin" (pprHsCtxt hs_ctxt)
|
|
| 2030 | + ; return $ hsCtxtCtOrigin hs_ctxt
|
|
| 2026 | 2031 | }
|
| 2027 | 2032 | |
| 2028 | 2033 |
| ... | ... | @@ -122,7 +122,8 @@ tcPolyLExpr, tcPolyLExprNC :: LHsExpr GhcRn -> ExpSigmaType |
| 122 | 122 | -> TcM (LHsExpr GhcTc)
|
| 123 | 123 | |
| 124 | 124 | tcPolyLExpr (L loc expr) res_ty
|
| 125 | - = addLExprCtxt (locA loc) expr $ -- Note [Error contexts in generated code]
|
|
| 125 | + = setSrcSpanA loc $
|
|
| 126 | + addExprCtxt expr $ -- Note [Error contexts in generated code]
|
|
| 126 | 127 | do { expr' <- tcPolyExpr expr res_ty
|
| 127 | 128 | ; return (L loc expr') }
|
| 128 | 129 | |
| ... | ... | @@ -250,9 +251,11 @@ tcInferExpr, tcInferExprNC :: InferInstFlag -> LHsExpr GhcRn -> TcM (LHsExpr Ghc |
| 250 | 251 | tcInferExpr = tc_infer_expr IFRR_Any
|
| 251 | 252 | tcInferExprNC = tc_infer_expr_NC IFRR_Any
|
| 252 | 253 | |
| 253 | -tc_infer_expr, tc_infer_expr_NC :: InferFRRFlag -> InferInstFlag -> LHsExpr GhcRn -> TcM (LHsExpr GhcTc, TcType)
|
|
| 254 | +tc_infer_expr, tc_infer_expr_NC :: InferFRRFlag -> InferInstFlag
|
|
| 255 | + -> LHsExpr GhcRn -> TcM (LHsExpr GhcTc, TcType)
|
|
| 254 | 256 | tc_infer_expr ifrr iif (L loc expr)
|
| 255 | - = addLExprCtxt (locA loc) expr $ -- Note [Error contexts in generated code]
|
|
| 257 | + = setSrcSpanA loc $
|
|
| 258 | + addExprCtxt expr $ -- Note [Error contexts in generated code]
|
|
| 256 | 259 | do { (expr', rho) <- runInfer iif ifrr (tcExpr expr)
|
| 257 | 260 | ; return (L loc expr', rho) }
|
| 258 | 261 | |
| ... | ... | @@ -278,9 +281,10 @@ tcMonoLExpr, tcMonoLExprNC |
| 278 | 281 | -> TcM (LHsExpr GhcTc)
|
| 279 | 282 | |
| 280 | 283 | tcMonoLExpr (L loc expr) res_ty
|
| 281 | - = do addLExprCtxt (locA loc) expr $ -- Note [Error contexts in generated code]
|
|
| 282 | - do { expr' <- tcExpr expr res_ty
|
|
| 283 | - ; return (L loc expr') }
|
|
| 284 | + = setSrcSpanA loc $
|
|
| 285 | + addExprCtxt expr $ -- Note [Error contexts in generated code]
|
|
| 286 | + do { expr' <- tcExpr expr res_ty
|
|
| 287 | + ; return (L loc expr') }
|
|
| 284 | 288 | |
| 285 | 289 | tcMonoLExprNC (L loc expr) res_ty
|
| 286 | 290 | = setSrcSpanA loc $
|
| ... | ... | @@ -813,9 +817,9 @@ The rest of this Note explains how that is done. |
| 813 | 817 | where `ee` is the expansion of the user written thing `ue`
|
| 814 | 818 | |
| 815 | 819 | * The type checker context has 3 key fields that describe the context:
|
| 816 | - TcLclCtxt { tcl_loc :: RealSrcSpan
|
|
| 820 | + TcLclCtxt { tcl_loc :: RealSrcSpan
|
|
| 817 | 821 | , tcl_in_gen_code :: Bool
|
| 818 | - , tcl_err_ctxt :: [ErrCtxt]
|
|
| 822 | + , tcl_err_ctxt :: ErrCtxtStack
|
|
| 819 | 823 | , ... }
|
| 820 | 824 | Note `tcl_loc` always points to a real place in the source code,
|
| 821 | 825 | hence `RealSrcSpan`.
|
| ... | ... | @@ -831,24 +835,20 @@ The rest of this Note explains how that is done. |
| 831 | 835 | |
| 832 | 836 | * Now, when
|
| 833 | 837 | tcMonoLExpr :: LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
|
| 834 | - gets a located expression, it does 2 things:
|
|
| 835 | - (a) Calls `addLExprCtxt` to perform error context management
|
|
| 836 | - (b) Calls `tcExpr` to typecheck the expression.
|
|
| 837 | - |
|
| 838 | -(a) `addLExprCtxt span expr`
|
|
| 839 | - (1) updates the location of `tcl_loc` with the `span` above,
|
|
| 840 | - (2) adds an `ErrCtxt` on top of the `tcl_err_ctxt`.
|
|
| 838 | + gets a located expression, it does 3 things:
|
|
| 839 | + (a) Calls `setSrcSpanA` to set the ambient source-code location
|
|
| 840 | + (b) Calls `addExprCtxt` to add a suitable `HsCtxt` on top of the `tcl_err_ctxt`.
|
|
| 841 | + (c) Calls `tcExpr` to typecheck the expression.
|
|
| 841 | 842 | |
| 842 | -* However, if the `span` is generated (see `isGeneratedSrcSpan`), then
|
|
| 843 | - `addLExprCtxt` sets `tcl_in_gen_code` to `True` via a call to `setSrcSpan`
|
|
| 844 | - and the `tcl_err_ctxt` is left untouched. Crucially, when we generate code in `expandExpr`,
|
|
| 845 | - all the generated AST notes are tagged with a `GeneratedSrcSpan`. This
|
|
| 846 | - is how we avoid populating the TcLclCtxt with generated code.
|
|
| 843 | +* In these calls, if the `span` is generated (see `isGeneratedSrcSpan`), then
|
|
| 844 | + - `setSrcSpanA` sets `tcl_in_gen_code` to `True`
|
|
| 845 | + - `addErrCtxt` is a no-op if `tcl_in_gen_code` is True
|
|
| 846 | + This is how we avoid populating the TcLclCtxt with generated code.
|
|
| 847 | 847 | |
| 848 | 848 | * The type checker error-stack element `GHC.Tc.Types.ErrCtxt.HsCtxt`
|
| 849 | 849 | just stores an error message
|
| 850 | 850 | |
| 851 | - type ErrCtxt = HsCtxt
|
|
| 851 | + type ErrCtxtStack = [HsCtxt]
|
|
| 852 | 852 | |
| 853 | 853 | When called on an `XExpr`, `addLExprCtxt`, adds the user written thing
|
| 854 | 854 | `ue`, and the error message provided by the caller on the `ErrCtxtStack` See
|
| ... | ... | @@ -473,7 +473,8 @@ tcInferAppHead_maybe fun = case fun of |
| 473 | 473 | |
| 474 | 474 | |
| 475 | 475 | |
| 476 | -with_get_ds :: TcM (HsExpr GhcTc, TcSigmaType) -> TcM (HsExpr GhcTc, DeepSubsumptionFlag, TcSigmaType)
|
|
| 476 | +with_get_ds :: TcM (HsExpr GhcTc, TcSigmaType)
|
|
| 477 | + -> TcM (HsExpr GhcTc, DeepSubsumptionFlag, TcSigmaType)
|
|
| 477 | 478 | with_get_ds mthing =
|
| 478 | 479 | do { (expr_tc, sig_ty) <- mthing
|
| 479 | 480 | ; ds_flag <- getDeepSubsumptionFlag_DataConHead expr_tc
|
| ... | ... | @@ -405,7 +405,7 @@ so that tcPat can extend the environment for the thing_inside, but also |
| 405 | 405 | so that constraints arising in the thing_inside can be discharged by the
|
| 406 | 406 | pattern.
|
| 407 | 407 | |
| 408 | -This does not work so well for the ErrCtxt carried by the monad: we don't
|
|
| 408 | +This does not work so well for the HsCtxt carried by the monad: we don't
|
|
| 409 | 409 | want the error-context for the pattern to scope over the RHS.
|
| 410 | 410 | Hence the getErrCtxt/setErrCtxt stuff in tcMultiple
|
| 411 | 411 | -}
|
| ... | ... | @@ -34,7 +34,7 @@ module GHC.Tc.Types( |
| 34 | 34 | FrontendResult(..),
|
| 35 | 35 | |
| 36 | 36 | -- Renamer types
|
| 37 | - ErrCtxt,
|
|
| 37 | + HsCtxt,
|
|
| 38 | 38 | ImportAvails(..), emptyImportAvails, plusImportAvails,
|
| 39 | 39 | ImportUserSpec(..),
|
| 40 | 40 | ImpUserList(..),
|
| ... | ... | @@ -439,7 +439,7 @@ pprCtLoc (CtLoc { ctl_origin = o, ctl_env = lcl}) |
| 439 | 439 | -- when reporting errors, see `setCtLocM`.
|
| 440 | 440 | --
|
| 441 | 441 | -- See also 'TcLclCtxt'.
|
| 442 | -data CtLocEnv = CtLocEnv { ctl_ctxt :: ![ErrCtxt]
|
|
| 442 | +data CtLocEnv = CtLocEnv { ctl_ctxt :: !ErrCtxtStack
|
|
| 443 | 443 | , ctl_loc :: !RealSrcSpan
|
| 444 | 444 | , ctl_bndrs :: !TcBinderStack
|
| 445 | 445 | , ctl_tclvl :: !TcLevel
|
| 1 | 1 | {-# LANGUAGE UndecidableInstances #-}
|
| 2 | 2 | |
| 3 | 3 | module GHC.Tc.Types.ErrCtxt
|
| 4 | - ( ErrCtxt, HsCtxt(..), isHsCtxtLandmark
|
|
| 4 | + ( HsCtxt(..), isHsCtxtLandmark
|
|
| 5 | 5 | , UserSigType(..), FunAppCtxtFunArg(..)
|
| 6 | 6 | , TyConInstFlavour(..)
|
| 7 | + , ErrCtxtStack
|
|
| 7 | 8 | |
| 8 | 9 | -- * UserTypeCtxt
|
| 9 | 10 | , UserTypeCtxt(..), pprUserTypeCtxt, isSigMaybe
|
| ... | ... | @@ -51,6 +52,7 @@ import qualified Data.List.NonEmpty as NE |
| 51 | 52 | {- *********************************************************************
|
| 52 | 53 | * *
|
| 53 | 54 | UserTypeCtxt
|
| 55 | +b
|
|
| 54 | 56 | * *
|
| 55 | 57 | ********************************************************************* -}
|
| 56 | 58 | |
| ... | ... | @@ -195,19 +197,14 @@ isSigMaybe _ = Nothing |
| 195 | 197 | |
| 196 | 198 | {- *********************************************************************
|
| 197 | 199 | * *
|
| 198 | - ErrCtxt
|
|
| 200 | + HsCtxt
|
|
| 201 | + Error message contexts
|
|
| 199 | 202 | * *
|
| 200 | 203 | ********************************************************************* -}
|
| 201 | ---------------------------------------------------------------------------------
|
|
| 202 | 204 | |
| 203 | --- type HsCtxtM = TidyEnv -> ZonkM (TidyEnv, HsCtxt)
|
|
| 204 | - |
|
| 205 | --- | Additional context to include in an error message, e.g.
|
|
| 206 | --- "In the type signature ...", "In the ambiguity check for ...", etc.
|
|
| 207 | -type ErrCtxt = HsCtxt
|
|
| 208 | - |
|
| 209 | ---------------------------------------------------------------------------------
|
|
| 210 | --- Error message contexts
|
|
| 205 | +-- An error-context stack (maintained in the typehcecker's monad)
|
|
| 206 | +-- is just a stack of HsCtxts
|
|
| 207 | +type ErrCtxtStack = [HsCtxt]
|
|
| 211 | 208 | |
| 212 | 209 | data UserSigType
|
| 213 | 210 | = UserLHsSigType !(LHsSigType GhcRn)
|
| ... | ... | @@ -21,7 +21,6 @@ module GHC.Tc.Types.LclEnv ( |
| 21 | 21 | , setLclEnvTypeEnv
|
| 22 | 22 | , modifyLclEnvTcLevel
|
| 23 | 23 | |
| 24 | - , getLclEnvHsCtxt
|
|
| 25 | 24 | , setLclEnvHsCtxt
|
| 26 | 25 | , setLclCtxtHsCtxt
|
| 27 | 26 | , lclEnvInGeneratedCode
|
| ... | ... | @@ -90,34 +89,6 @@ data TcLclEnv -- Changes as we move inside an expression |
| 90 | 89 | tcl_errs :: TcRef (Messages TcRnMessage) -- Place to accumulate diagnostics
|
| 91 | 90 | }
|
| 92 | 91 | |
| 93 | -{-
|
|
| 94 | - |
|
| 95 | -Note [ErrCtxtStack Manipulation]
|
|
| 96 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 97 | -The ErrCtxtStack is a list of ErrCtxt
|
|
| 98 | - |
|
| 99 | -This data structure keeps track of two things:
|
|
| 100 | -1. Are we type checking a compiler generated/non-user written code.
|
|
| 101 | -2. The trail of the error messages that have been added in route to the current expression
|
|
| 102 | - |
|
| 103 | -* When the `ErrCtxtStack` is a `UserCodeCtxt`,
|
|
| 104 | - - the current expression being typechecked is user written
|
|
| 105 | -* When the `ErrorCtxtStack` is a `ExpansionCodeCtxt`
|
|
| 106 | - - the current expression being typechecked is compiler generated/expanded;
|
|
| 107 | - - the original source code thing is stored in `src_code_origin` field.
|
|
| 108 | - - the `src_code_origin` is what will be used in the error message displayed to the user
|
|
| 109 | - |
|
| 110 | -In the current design, if the top of the ErrCtxtStack is an ExpansionCodeCtxt
|
|
| 111 | -i.e. we are currently typechecking a compiler generated expression, and we encounter
|
|
| 112 | -an XExpr, then we _replace_ the top of the stack with the new XExpr. Otherwise, we
|
|
| 113 | -push the new expression error message on top of the stack. cf. `LclEnv.setLclCtxtHsCtxt`
|
|
| 114 | - |
|
| 115 | --}
|
|
| 116 | - |
|
| 117 | - |
|
| 118 | --- See Note [ErrCtxtStack Manipulation]
|
|
| 119 | -type ErrCtxtStack = [ErrCtxt]
|
|
| 120 | - |
|
| 121 | 92 | -- | Get the top of the error message stack
|
| 122 | 93 | get_err_ctxt_stack_head :: ErrCtxtStack -> HsCtxt
|
| 123 | 94 | get_err_ctxt_stack_head (e : _) = e
|
| ... | ... | @@ -127,7 +98,7 @@ data TcLclCtxt |
| 127 | 98 | = TcLclCtxt {
|
| 128 | 99 | tcl_loc :: RealSrcSpan, -- Source span
|
| 129 | 100 | tcl_in_gen_code :: Bool, -- Are we type checking a generated expression?
|
| 130 | - tcl_err_ctxt :: ErrCtxtStack, -- See Note [ErrCtxtStack Manipulation]
|
|
| 101 | + tcl_err_ctxt :: ErrCtxtStack,
|
|
| 131 | 102 | tcl_tclvl :: TcLevel,
|
| 132 | 103 | tcl_bndrs :: TcBinderStack, -- Used for reporting relevant bindings,
|
| 133 | 104 | -- and for tidying type
|
| ... | ... | @@ -191,26 +162,23 @@ setLclEnvLoc loc = modifyLclCtxt (\lenv -> lenv { tcl_loc = loc }) |
| 191 | 162 | getLclEnvLoc :: TcLclEnv -> RealSrcSpan
|
| 192 | 163 | getLclEnvLoc = tcl_loc . tcl_lcl_ctxt
|
| 193 | 164 | |
| 194 | -getLclEnvErrCtxt :: TcLclEnv -> [ErrCtxt]
|
|
| 165 | +getLclEnvErrCtxt :: TcLclEnv -> ErrCtxtStack
|
|
| 195 | 166 | getLclEnvErrCtxt = tcl_err_ctxt . tcl_lcl_ctxt
|
| 196 | 167 | |
| 197 | 168 | setLclEnvErrCtxt :: ErrCtxtStack -> TcLclEnv -> TcLclEnv
|
| 198 | 169 | setLclEnvErrCtxt ctxt = modifyLclCtxt (\env -> env { tcl_err_ctxt = ctxt })
|
| 199 | 170 | |
| 200 | 171 | -- See Note [ErrCtxtStack Manipulation]
|
| 201 | -addLclEnvErrCtxt :: ErrCtxt -> TcLclEnv -> TcLclEnv
|
|
| 172 | +addLclEnvErrCtxt :: HsCtxt -> TcLclEnv -> TcLclEnv
|
|
| 202 | 173 | addLclEnvErrCtxt ec = setLclEnvHsCtxt ec
|
| 203 | 174 | |
| 204 | -getLclEnvHsCtxt :: TcLclEnv -> HsCtxt
|
|
| 205 | -getLclEnvHsCtxt = get_err_ctxt_stack_head . tcl_err_ctxt . tcl_lcl_ctxt
|
|
| 206 | - |
|
| 207 | -setLclEnvHsCtxt :: ErrCtxt -> TcLclEnv -> TcLclEnv
|
|
| 175 | +setLclEnvHsCtxt :: HsCtxt -> TcLclEnv -> TcLclEnv
|
|
| 208 | 176 | setLclEnvHsCtxt ec = modifyLclCtxt (setLclCtxtHsCtxt ec)
|
| 209 | 177 | |
| 210 | 178 | -- See Note [ErrCtxtStack Manipulation]
|
| 211 | -setLclCtxtHsCtxt :: ErrCtxt -> TcLclCtxt -> TcLclCtxt
|
|
| 179 | +setLclCtxtHsCtxt :: HsCtxt -> TcLclCtxt -> TcLclCtxt
|
|
| 212 | 180 | setLclCtxtHsCtxt ec lclCtxt
|
| 213 | - -- never stack 2 statement error contexts on top of each other
|
|
| 181 | + -- Never stack 2 statement error contexts on top of each other
|
|
| 214 | 182 | | StmtErrCtxt{} : ecs <- tcl_err_ctxt lclCtxt
|
| 215 | 183 | , StmtErrCtxt{} <- ec
|
| 216 | 184 | = lclCtxt { tcl_err_ctxt = ec : ecs }
|
| ... | ... | @@ -61,7 +61,6 @@ module GHC.Tc.Utils.Monad( |
| 61 | 61 | addDependentFiles, addDependentDirectories,
|
| 62 | 62 | |
| 63 | 63 | -- * Error management
|
| 64 | - getHsCtxt,
|
|
| 65 | 64 | getSrcSpanM, getRealSrcSpanM, setSrcSpan, setSrcSpanA, addLocM,
|
| 66 | 65 | inGeneratedCode,
|
| 67 | 66 | wrapLocM, wrapLocFstM, wrapLocFstMA, wrapLocSndM, wrapLocSndMA, wrapLocM_,
|
| ... | ... | @@ -88,7 +87,7 @@ module GHC.Tc.Utils.Monad( |
| 88 | 87 | |
| 89 | 88 | -- * Context management for the type checker
|
| 90 | 89 | getErrCtxt, setErrCtxt, addErrCtxt,
|
| 91 | - addLExprCtxt,
|
|
| 90 | + addExprCtxt,
|
|
| 92 | 91 | popErrCtxt, getCtLocM, setCtLocM, mkCtLocEnv,
|
| 93 | 92 | |
| 94 | 93 | -- * Diagnostic message generation (type checker)
|
| ... | ... | @@ -98,7 +97,7 @@ module GHC.Tc.Utils.Monad( |
| 98 | 97 | checkTc, checkTcM,
|
| 99 | 98 | checkJustTc, checkJustTcM,
|
| 100 | 99 | failIfTc, failIfTcM,
|
| 101 | - mkErrCtxt,
|
|
| 100 | + tidyErrCtxt,
|
|
| 102 | 101 | addTcRnDiagnostic, addDetailedDiagnostic,
|
| 103 | 102 | mkTcRnMessage, reportDiagnostic, reportDiagnostics,
|
| 104 | 103 | warnIf, diagnosticTc, diagnosticTcM,
|
| ... | ... | @@ -1086,7 +1085,15 @@ inGeneratedCode = lclEnvInGeneratedCode <$> getLclEnv |
| 1086 | 1085 | |
| 1087 | 1086 | setSrcSpan :: SrcSpan -> TcRn a -> TcRn a
|
| 1088 | 1087 | -- See Note [Error contexts in generated code]
|
| 1089 | --- NB: This is the only place where tcl_in_gen_code is modified
|
|
| 1088 | +-- When entering a node decorated with a /user/ span:
|
|
| 1089 | +-- * Record that span in `tcl_loc`
|
|
| 1090 | +-- * Set `tcl_in_gen_code` to False, to record that we
|
|
| 1091 | +-- are in user code.
|
|
| 1092 | +-- When entering a node decorated with a /generated/ span:
|
|
| 1093 | +-- * Do not touch `tcl_loc`, so that `tcl_loc` always records
|
|
| 1094 | +-- the innermost user span.
|
|
| 1095 | +-- NB: This is the only place where `tcl_loc` and `tcl_in_gen_code`
|
|
| 1096 | +-- are modified
|
|
| 1090 | 1097 | setSrcSpan (RealSrcSpan loc _) thing_inside
|
| 1091 | 1098 | = updLclCtxt (\ctxt -> ctxt {tcl_loc = loc, tcl_in_gen_code = False}) thing_inside
|
| 1092 | 1099 | setSrcSpan (GeneratedSrcSpan{}) thing_inside
|
| ... | ... | @@ -1094,9 +1101,6 @@ setSrcSpan (GeneratedSrcSpan{}) thing_inside |
| 1094 | 1101 | setSrcSpan _ thing_inside
|
| 1095 | 1102 | = thing_inside
|
| 1096 | 1103 | |
| 1097 | -getHsCtxt :: TcRn HsCtxt
|
|
| 1098 | -getHsCtxt = getLclEnvHsCtxt <$> getLclEnv
|
|
| 1099 | - |
|
| 1100 | 1104 | setSrcSpanA :: EpAnn ann -> TcRn a -> TcRn a
|
| 1101 | 1105 | setSrcSpanA l = setSrcSpan (locA l)
|
| 1102 | 1106 | |
| ... | ... | @@ -1177,7 +1181,7 @@ addErrAt :: SrcSpan -> TcRnMessage -> TcRn () |
| 1177 | 1181 | -- work doesn't matter
|
| 1178 | 1182 | addErrAt loc msg = do { ctxt <- getErrCtxt
|
| 1179 | 1183 | ; tidy_env <- liftZonkM $ tcInitTidyEnv
|
| 1180 | - ; err_ctxt <- mkErrCtxt tidy_env ctxt
|
|
| 1184 | + ; err_ctxt <- tidyErrCtxt tidy_env ctxt
|
|
| 1181 | 1185 | ; let detailed_msg = mkDetailedMessage (ErrInfo err_ctxt Nothing noHints) msg
|
| 1182 | 1186 | ; add_long_err_at loc detailed_msg }
|
| 1183 | 1187 | |
| ... | ... | @@ -1314,57 +1318,49 @@ problem. |
| 1314 | 1318 | |
| 1315 | 1319 | Note [Error contexts in generated code]
|
| 1316 | 1320 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 1317 | -* setSrcSpan is the only place that modifies `tcl_in_gen_code`
|
|
| 1321 | +* setSrcSpan is the only place that modifies `tcl_loc` and `tcl_in_gen_code`
|
|
| 1318 | 1322 | |
| 1319 | -* addLExpr updates updates the ErrCtxt stored in LclEnv with the following logic
|
|
| 1320 | - - If the `SrcSpan` is a `RealSrcSpan`, `setSrcSpan` updates the `tcl_loc` to the given value
|
|
| 1321 | - and sets `tcl_in_gen_code` to `False`. Meaning we are not type checking a compiler generated
|
|
| 1322 | - expression. And thus it can add the expression on to the ErrCtxt Stack
|
|
| 1323 | - - If the `SrcSpan` is a GeneratedSrcSpan then `tcl_in_gen_code` is set to `True`, meaning
|
|
| 1324 | - the expression in hand is compiler generated, and hence it is not added on to the stack.
|
|
| 1323 | +* addLExpr updates updates the HsCtxt stored in LclEnv with the following logic
|
|
| 1324 | + - If `tcl_in_gen_code` is true, do nothing
|
|
| 1325 | + - Otherwise push a suitable HsCtxt onto the ErrCtxtStack
|
|
| 1325 | 1326 | |
| 1326 | 1327 | This ensures that the error messages do not leak compiler generated expressions which can
|
| 1327 | 1328 | be confusing to the users as they never appear in the original source code
|
| 1328 | 1329 | |
| 1329 | - |
|
| 1330 | 1330 | - See Note [Rebindable syntax and XXExprGhcRn] in `GHC.Hs.Expr` for
|
| 1331 | -more discussion of this fancy footwork
|
|
| 1331 | + more discussion of this fancy footwork
|
|
| 1332 | 1332 | - See Note [Generated code and pattern-match checking] in `GHC.Types.Basic` for the
|
| 1333 | -relation with pattern-match checks
|
|
| 1334 | -- See Note [ErrCtxtStack Manipulation] in `GHC.Tc.Types.LclEnv` for info about `ErrCtxtStack`
|
|
| 1333 | + relation with pattern-match checks
|
|
| 1335 | 1334 | -}
|
| 1336 | 1335 | |
| 1337 | 1336 | -- See Note [Error contexts in generated code]
|
| 1338 | -addLExprCtxt :: SrcSpan -> HsExpr GhcRn -> TcRn a -> TcRn a
|
|
| 1339 | -addLExprCtxt lspan e thing_inside
|
|
| 1340 | - = setSrcSpan lspan $ add_expr_ctxt e thing_inside
|
|
| 1341 | - where
|
|
| 1342 | - add_expr_ctxt :: HsExpr GhcRn -> TcRn a -> TcRn a
|
|
| 1343 | - add_expr_ctxt e thing_inside
|
|
| 1344 | - = do { igc <- inGeneratedCode
|
|
| 1345 | - ; if igc -- generated
|
|
| 1346 | - then thing_inside
|
|
| 1347 | - else case e of
|
|
| 1348 | - -- The HsHole special case addresses situations like
|
|
| 1349 | - -- f x = _
|
|
| 1350 | - -- when we don't want to say "In the expression: _",
|
|
| 1351 | - -- because it is mentioned in the error message itself
|
|
| 1352 | - HsHole{} -> thing_inside
|
|
| 1353 | - |
|
| 1354 | - -- There is a special case for expressions with signatures to avoid having too verbose
|
|
| 1355 | - -- error context. c.f. RecordDotSyntaxFail9
|
|
| 1356 | - -- Add the original HsCtxt if we are typechecking an expanded expression
|
|
| 1357 | - ExprWithTySig _ (L _ e') _
|
|
| 1358 | - | XExpr (ExpandedThingRn (HSE o _)) <- e' -> addErrCtxt o thing_inside
|
|
| 1359 | - XExpr (ExpandedThingRn (HSE o _)) -> addErrCtxt o thing_inside
|
|
| 1360 | - |
|
| 1361 | - _ -> addErrCtxt (ExprCtxt e) thing_inside
|
|
| 1362 | - }
|
|
| 1363 | - |
|
| 1364 | -getErrCtxt :: TcM [ErrCtxt]
|
|
| 1337 | +addExprCtxt :: HsExpr GhcRn -> TcRn a -> TcRn a
|
|
| 1338 | +addExprCtxt e thing_inside
|
|
| 1339 | + = do { igc <- inGeneratedCode
|
|
| 1340 | + ; if igc -- In generated code; so addExprCtxt is a no-op
|
|
| 1341 | + then thing_inside
|
|
| 1342 | + else case e of
|
|
| 1343 | + -- The HsHole special case addresses situations like
|
|
| 1344 | + -- f x = _
|
|
| 1345 | + -- when we don't want to say "In the expression: _",
|
|
| 1346 | + -- because it is mentioned in the error message itself
|
|
| 1347 | + HsHole{} -> thing_inside
|
|
| 1348 | + |
|
| 1349 | + -- There is a special case for expressions with signatures to avoid having
|
|
| 1350 | + -- too verbose error context. c.f. RecordDotSyntaxFail9
|
|
| 1351 | + -- Add the original HsCtxt if we are typechecking an expanded expression
|
|
| 1352 | + ExprWithTySig _ (L _ e') _
|
|
| 1353 | + | XExpr (ExpandedThingRn (HSE o _)) <- e' -> addErrCtxt o thing_inside
|
|
| 1354 | + |
|
| 1355 | + XExpr (ExpandedThingRn (HSE o _)) -> addErrCtxt o thing_inside
|
|
| 1356 | + |
|
| 1357 | + _ -> addErrCtxt (ExprCtxt e) thing_inside
|
|
| 1358 | + }
|
|
| 1359 | + |
|
| 1360 | +getErrCtxt :: TcM ErrCtxtStack
|
|
| 1365 | 1361 | getErrCtxt = do { env <- getLclEnv; return (getLclEnvErrCtxt env) }
|
| 1366 | 1362 | |
| 1367 | -setErrCtxt :: [ErrCtxt] -> TcM a -> TcM a
|
|
| 1363 | +setErrCtxt :: ErrCtxtStack -> TcM a -> TcM a
|
|
| 1368 | 1364 | {-# INLINE setErrCtxt #-} -- Note [Inlining addErrCtxt]
|
| 1369 | 1365 | setErrCtxt ctxt = updLclEnv (setLclEnvErrCtxt ctxt)
|
| 1370 | 1366 | |
| ... | ... | @@ -1374,7 +1370,7 @@ addErrCtxt :: HsCtxt -> TcM a -> TcM a |
| 1374 | 1370 | addErrCtxt ctxt = pushCtxt ctxt
|
| 1375 | 1371 | |
| 1376 | 1372 | -- See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr
|
| 1377 | -pushCtxt :: ErrCtxt -> TcM a -> TcM a
|
|
| 1373 | +pushCtxt :: HsCtxt -> TcM a -> TcM a
|
|
| 1378 | 1374 | {-# INLINE pushCtxt #-} -- Note [Inlining addErrCtxt]
|
| 1379 | 1375 | pushCtxt ctxt = updLclEnv (addLclEnvErrCtxt ctxt)
|
| 1380 | 1376 | |
| ... | ... | @@ -1868,7 +1864,7 @@ addDiagnosticTc msg |
| 1868 | 1864 | addDiagnosticTcM :: (TidyEnv, TcRnMessage) -> TcM ()
|
| 1869 | 1865 | addDiagnosticTcM (env0, msg)
|
| 1870 | 1866 | = do { ctxt <- getErrCtxt
|
| 1871 | - ; extra <- mkErrCtxt env0 ctxt
|
|
| 1867 | + ; extra <- tidyErrCtxt env0 ctxt
|
|
| 1872 | 1868 | ; let detailed_msg = mkDetailedMessage (ErrInfo extra Nothing noHints) msg
|
| 1873 | 1869 | ; add_diagnostic detailed_msg }
|
| 1874 | 1870 | |
| ... | ... | @@ -1881,7 +1877,7 @@ addDetailedDiagnostic mkMsg = do |
| 1881 | 1877 | !diag_opts <- initDiagOpts <$> getDynFlags
|
| 1882 | 1878 | env0 <- liftZonkM tcInitTidyEnv
|
| 1883 | 1879 | ctxt <- getErrCtxt
|
| 1884 | - err_info <- mkErrCtxt env0 ctxt
|
|
| 1880 | + err_info <- tidyErrCtxt env0 ctxt
|
|
| 1885 | 1881 | reportDiagnostic $
|
| 1886 | 1882 | mkMsgEnvelope diag_opts loc name_ppr_ctx $
|
| 1887 | 1883 | mkMsg err_info
|
| ... | ... | @@ -1918,16 +1914,19 @@ add_diagnostic msg |
| 1918 | 1914 | -}
|
| 1919 | 1915 | |
| 1920 | 1916 | add_err_tcm :: TidyEnv -> TcRnMessage -> SrcSpan
|
| 1921 | - -> [ErrCtxt]
|
|
| 1917 | + -> ErrCtxtStack
|
|
| 1922 | 1918 | -> TcM ()
|
| 1923 | 1919 | add_err_tcm tidy_env msg loc ctxt
|
| 1924 | - = do { err_ctxt <- mkErrCtxt tidy_env ctxt
|
|
| 1920 | + = do { err_ctxt <- tidyErrCtxt tidy_env ctxt
|
|
| 1925 | 1921 | ; add_long_err_at loc $
|
| 1926 | 1922 | mkDetailedMessage (ErrInfo err_ctxt Nothing noHints) msg }
|
| 1927 | 1923 | |
| 1928 | -mkErrCtxt :: TidyEnv -> [ErrCtxt] -> TcM [HsCtxt]
|
|
| 1929 | --- Tidy the error info, trimming excessive contexts
|
|
| 1930 | -mkErrCtxt env ctxts
|
|
| 1924 | +tidyErrCtxt :: TidyEnv -> ErrCtxtStack -> TcM ErrCtxtStack
|
|
| 1925 | +-- Do the following
|
|
| 1926 | +-- * Zonk each HsCtxt in the ErrCtxtStack
|
|
| 1927 | +-- * Tidy each using TidyEnv
|
|
| 1928 | +-- * Trim excessive contexts
|
|
| 1929 | +tidyErrCtxt env ctxts
|
|
| 1931 | 1930 | -- = do
|
| 1932 | 1931 | -- dbg <- hasPprDebug <$> getDynFlags
|
| 1933 | 1932 | -- if dbg -- In -dppr-debug style the output
|
| ... | ... | @@ -1935,7 +1934,7 @@ mkErrCtxt env ctxts |
| 1935 | 1934 | -- else go dbg 0 env ctxts
|
| 1936 | 1935 | = go False 0 env ctxts -- regular error ctx
|
| 1937 | 1936 | where
|
| 1938 | - go :: Bool -> Int -> TidyEnv -> [ErrCtxt] -> TcM [HsCtxt]
|
|
| 1937 | + go :: Bool -> Int -> TidyEnv -> ErrCtxtStack -> TcM ErrCtxtStack
|
|
| 1939 | 1938 | go _ _ _ [] = return []
|
| 1940 | 1939 | go dbg n env (ctxt : ctxts)
|
| 1941 | 1940 | | isHsCtxtLandmark ctxt
|
| ... | ... | @@ -2698,11 +2698,11 @@ uType_defer (UE { u_loc = loc, u_defer = ref |
| 2698 | 2698 | -- snocBag: see Note [Work-list ordering] in GHC.Tc.Solver.Equality
|
| 2699 | 2699 | |
| 2700 | 2700 | -- Error trace only
|
| 2701 | - -- NB. do *not* call mkErrCtxt unless tracing is on,
|
|
| 2701 | + -- NB. do *not* call tidyErrCtxt unless tracing is on,
|
|
| 2702 | 2702 | -- because it is hugely expensive (#5631)
|
| 2703 | 2703 | ; whenDOptM Opt_D_dump_tc_trace $
|
| 2704 | 2704 | do { ctxt <- getErrCtxt
|
| 2705 | - ; err_ctxt <- mkErrCtxt emptyTidyEnv ctxt
|
|
| 2705 | + ; err_ctxt <- tidyErrCtxt emptyTidyEnv ctxt
|
|
| 2706 | 2706 | ; traceTc "utype_defer" $
|
| 2707 | 2707 | vcat ( ppr role
|
| 2708 | 2708 | : debugPprType ty1
|
| ... | ... | @@ -798,6 +798,8 @@ tidyEvVar env var = updateIdTypeAndMult (tidyType env) var |
| 798 | 798 | |
| 799 | 799 | |
| 800 | 800 | zonkTidyHsCtxt :: TidyEnv -> HsCtxt -> ZonkM (TidyEnv, HsCtxt)
|
| 801 | +-- We zonk and tidy a HsCtxt just before putting it into an error message
|
|
| 802 | +-- so that it contains as much info as possible, as tidily as possible
|
|
| 801 | 803 | zonkTidyHsCtxt env e@(ExprCtxt{}) = return (env, e)
|
| 802 | 804 | zonkTidyHsCtxt env (ThetaCtxt ctxt theta_ty) = do
|
| 803 | 805 | (env', theta_ty') <- zonkTidyTcTypes env theta_ty
|
| ... | ... | @@ -152,7 +152,7 @@ I.1. GHC.Tc.Zonk.Monad - the ZonkM monad |
| 152 | 152 | as used in GHC.Tc.Zonk.TcType.
|
| 153 | 153 | |
| 154 | 154 | Crucially, it never errors. It is the monad we use when reporting errors
|
| 155 | - (see ErrCtxt), and it would be quite bad if we could error in the middle
|
|
| 155 | + (see HsCtxt), and it would be quite bad if we could error in the middle
|
|
| 156 | 156 | of reporting an error!
|
| 157 | 157 | |
| 158 | 158 | I.2. GHC.Tc.Zonk.TcType - zonking types in the typechecker
|