Simon Peyton Jones pushed to branch wip/spj-apporv-Oct24 at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • compiler/GHC/Tc/Gen/Expr.hs
    ... ... @@ -762,47 +762,73 @@ tcExpr (SectionR {}) ty = pprPanic "tcExpr:SectionR" (ppr ty)
    762 762
     ************************************************************************
    
    763 763
     -}
    
    764 764
     
    
    765
    -{- Note [Overview of Typechecking an XExpr]
    
    766
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    767
    -Certain constructs undergo expansion right before type checking.
    
    765
    +{- Note [Typechecking by expansion: overview]
    
    766
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    767
    +For many constructs, rather than typechecking the user-written code
    
    768
    +directly, it's much easier to
    
    769
    +   * Expand (or desugar) the code to something simpler
    
    770
    +   * Typecheck that simpler expression
    
    768 771
     
    
    769
    -   tcExpr ue@(RecordUpd{}) rho = do { ee <- expand e; tcExpr ee rho }
    
    772
    +Example: record updates.  The typechecker looks like this:
    
    770 773
     
    
    771
    -See Note [Handling overloaded and rebindable constructs] and
    
    772
    -Note [Doing XXExprGhcRn in the Renamer vs Typechecker]
    
    773
    -for details about which constructs are expanded.
    
    774
    +   tcExpr e@(RecordUpd{}) rho = do { ee <- expandExpr e
    
    775
    +                                   ; tcExpr ee rho }
    
    774 776
     
    
    775
    -The expansion process typically takes a user written thing
    
    776
    -       L lspan ue
    
    777
    -and returns
    
    778
    -       L lspan (XExpr (ExpandedThingRn { xrn_orig = ue
    
    779
    -                                       , xrn_expanded = ee } ))
    
    777
    +The `expandExpr` replaces the record update (e { x = rhs })
    
    778
    +with something like
    
    779
    +   case e of { MkT a b _ d -> MkT a b rhs d }
    
    780
    +and we then typecheck the latter.
    
    780 781
     
    
    781
    -where `ee` is the expansion of the user written thing `ue`
    
    782
    +See also Note [Handling overloaded and rebindable constructs]
    
    783
    +     and Note [Doing XXExprGhcRn in the Renamer vs Typechecker]
    
    782 784
     
    
    783
    -Now, when a `tcMonoLHsExpr :: LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)`
    
    784
    -gets a located expression, It does 2 things:
    
    785
    -1. calls `addLExprCtxt` to perform error context management, and;
    
    786
    -2. calls tcExpr to typecheck the expression.
    
    785
    +The Big Question is how to ensure that error messages mention
    
    786
    +only user-written source code, and never talk about the expanded code.
    
    787
    +The rest of this Note explains how that is done.
    
    787 788
     
    
    788
    -The type checker context has 2 key fields:
    
    789
    +* The expansion process typically takes a user written thing
    
    790
    +       L lspan ue
    
    791
    +  and returns
    
    792
    +       L lspan (XExpr (ExpandedThingRn { xrn_orig = ue
    
    793
    +                                       , xrn_expanded = ee } ))
    
    794
    +  where `ee` is the expansion of the user written thing `ue`
    
    789 795
     
    
    790
    -     TcLclCtxt { tcl_loc         :: RealSrcSpan
    
    791
    -               , tcl_err_ctxt    :: [ErrCtxt]
    
    796
    +* The type checker context has 2 key fields that describe the context:
    
    797
    +     TcLclCtxt { tcl_loc      :: RealSrcSpan
    
    798
    +               , tcl_err_ctxt :: [ErrCtxt]
    
    792 799
                    , ... }
    
    793
    -
    
    794
    -When called on an XExpr, `addLExprCtxt` updates the location of `tcl_loc` with
    
    795
    -the `lspan` above and adds an ErrCtxt on top of the `tcl_err_ctxt`. If the
    
    796
    -`lspan` is generated, then `addLExprCtxt` is a no-op.
    
    797
    -
    
    798
    -The type checker error stack element `GHC.Tc.Types.ErrCtxt.ErrCtxt` has two fields
    
    799
    -
    
    800
    -     ErrCtxt = EC CodeSrcFlag ErrCtxtMsgM
    
    801
    -
    
    802
    -`CodeSrcFlag` says whether we are typechecking an expanded thing, and what that expanded thing is
    
    803
    -`ErrCtxtMsgM` stores the pre-text error message itself. When called on an `XExpr`, `addLExprCtxt`,
    
    804
    -adds the user written thing `ue`, and the error message provided by the caller on the `ErrCtxtStack`
    
    805
    -See Note [ErrCtxtStack Manipulation] for more details.
    
    800
    +  Note `tcl_loc` always points to a real place in the source code,
    
    801
    +  hence `RealSrcSpan`.
    
    802
    +
    
    803
    +  The `tcl_err_ctxt` is a stack of contexts, each saying something
    
    804
    +  like "In the expression: x+y" or "In the record update: r { x=2 }"
    
    805
    +
    
    806
    +* Now, when
    
    807
    +      tcMonoLHsExpr :: LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    808
    +  gets a located expression, it does 2 things:
    
    809
    +    * Calls `addLExprCtxt` to perform error context management
    
    810
    +    * Calls `tcExpr` to typecheck the expression.
    
    811
    +
    
    812
    +* `addLExprCtxt span expr`
    
    813
    +    (1) updates the location of `tcl_loc` with the `span` above,
    
    814
    +    (2) adds an `ErrCtxt` on top of the `tcl_err_ctxt`.
    
    815
    +
    
    816
    +* However, if the `span` is generated (see `isGeneratedSrcSpan`), then
    
    817
    +  `addLExprCtxt` is a no-op. Crucially, when we generate code in `expandExpr`,
    
    818
    +  all the generated AST notes are tagged with a `GeneratedSrcSpan`. This
    
    819
    +  is how we avoid populating the TcLclCtxt with generated code.
    
    820
    +
    
    821
    +* The type checker error-stack element `GHC.Tc.Types.ErrCtxt.ErrCtxt`
    
    822
    +  has two fields
    
    823
    +     data ErrCtxt = EC ErrCtxt
    
    824
    +
    
    825
    +    * `CodeSrcFlag` says whether we are typechecking an expanded thing,
    
    826
    +      and what that expanded thing is
    
    827
    +    * `ErrCtxtMsgM` stores the pre-text error message itself.
    
    828
    +
    
    829
    +  When called on an `XExpr`, `addLExprCtxt`, adds the user written thing
    
    830
    +  `ue`, and the error message provided by the caller on the `ErrCtxtStack` See
    
    831
    +  Note [ErrCtxtStack Manipulation] for more details.
    
    806 832
     
    
    807 833
     -}
    
    808 834
     
    

  • compiler/GHC/Tc/Gen/Head.hs
    ... ... @@ -19,8 +19,7 @@ module GHC.Tc.Gen.Head
    19 19
            , tyConOf, tyConOfET
    
    20 20
            , nonBidirectionalErr
    
    21 21
     
    
    22
    -       , pprArgInst
    
    23
    -       , addLExprCtxt, addFunResCtxt ) where
    
    22
    +       , pprArgInst, addFunResCtxt ) where
    
    24 23
     
    
    25 24
     import {-# SOURCE #-} GHC.Tc.Gen.Expr( tcExpr, tcCheckPolyExprNC, tcPolyLExprSig )
    
    26 25
     import {-# SOURCE #-} GHC.Tc.Gen.Splice( getUntypedSpliceBody )
    
    ... ... @@ -1076,39 +1075,3 @@ Notice that tcSplitNestedSigmaTys looks through function arrows too, regardless
    1076 1075
     of simple/deep subsumption.  Here we are concerned only whether there is a
    
    1077 1076
     mis-match in the number of value arguments.
    
    1078 1077
     -}
    1079
    -
    
    1080
    -
    
    1081
    -{- *********************************************************************
    
    1082
    -*                                                                      *
    
    1083
    -             Misc utility functions
    
    1084
    -*                                                                      *
    
    1085
    -********************************************************************* -}
    
    1086
    -
    
    1087
    --- | !Caution!: Users should not call add_expr_ctxt, they ought to use addLExprCtxt
    
    1088
    -add_expr_ctxt :: HsExpr GhcRn -> TcRn a -> TcRn a
    
    1089
    -add_expr_ctxt e thing_inside
    
    1090
    -  = case e of
    
    1091
    -      HsHole{} -> thing_inside
    
    1092
    -   -- The HsHole special case addresses situations like
    
    1093
    -   --    f x = _
    
    1094
    -   -- when we don't want to say "In the expression: _",
    
    1095
    -   -- because it is mentioned in the error message itself
    
    1096
    -
    
    1097
    -      ExprWithTySig _ (L _ e') _
    
    1098
    -        | XExpr (ExpandedThingRn o _) <- e' -> addExpansionErrCtxt o (ExprCtxt e) thing_inside
    
    1099
    -   -- There is a special case for expressions with signatures to avoid having too verbose
    
    1100
    -   -- error context. So here we flip the ErrCtxt state to expanded if the expression is expanded.
    
    1101
    -   -- c.f. RecordDotSyntaxFail9
    
    1102
    -
    
    1103
    -      XExpr (ExpandedThingRn o _) -> addExpansionErrCtxt o (srcCodeOriginErrCtxMsg o) thing_inside
    
    1104
    -   -- Flip error ctxt into expansion mode
    
    1105
    -
    
    1106
    -      _ -> addErrCtxt (ExprCtxt e) thing_inside
    
    1107
    -
    
    1108
    -
    
    1109
    -addLExprCtxt :: SrcSpan -> HsExpr GhcRn -> TcRn a -> TcRn a
    
    1110
    -addLExprCtxt lspan e thing_inside
    
    1111
    -  | not (isGeneratedSrcSpan lspan)
    
    1112
    -  = setSrcSpan lspan $ add_expr_ctxt e thing_inside
    
    1113
    -  | otherwise   -- no op in generated code
    
    1114
    -  = thing_inside

  • compiler/GHC/Tc/Utils/Monad.hs
    ... ... @@ -88,7 +88,7 @@ module GHC.Tc.Utils.Monad(
    88 88
     
    
    89 89
       -- * Context management for the type checker
    
    90 90
       getErrCtxt, setErrCtxt, addErrCtxt, addErrCtxtM, addLandmarkErrCtxt,
    
    91
    -  addExpansionErrCtxt, addExpansionErrCtxtM,
    
    91
    +  addLExprCtxt, addExpansionErrCtxt, addExpansionErrCtxtM,
    
    92 92
       addLandmarkErrCtxtM, popErrCtxt, getCtLocM, setCtLocM, mkCtLocEnv,
    
    93 93
     
    
    94 94
       -- * Diagnostic message generation (type checker)
    
    ... ... @@ -1324,6 +1324,35 @@ relation with pattern-match checks
    1324 1324
     - See Note [ErrCtxtStack Manipulation] in `GHC.Tc.Types.LclEnv` for info about `ErrCtxtStack`
    
    1325 1325
     -}
    
    1326 1326
     
    
    1327
    +addLExprCtxt :: SrcSpan -> HsExpr GhcRn -> TcRn a -> TcRn a
    
    1328
    +addLExprCtxt lspan e thing_inside
    
    1329
    +  | not (isGeneratedSrcSpan lspan)
    
    1330
    +  = setSrcSpan lspan $ add_expr_ctxt e thing_inside
    
    1331
    +  | otherwise   -- no op in generated code
    
    1332
    +  = thing_inside
    
    1333
    +
    
    1334
    +-- | !Caution!: Users should not call add_expr_ctxt, they ought to use addLExprCtxt
    
    1335
    +add_expr_ctxt :: HsExpr GhcRn -> TcRn a -> TcRn a
    
    1336
    +add_expr_ctxt e thing_inside
    
    1337
    +  = case e of
    
    1338
    +      HsHole{} -> thing_inside
    
    1339
    +   -- The HsHole special case addresses situations like
    
    1340
    +   --    f x = _
    
    1341
    +   -- when we don't want to say "In the expression: _",
    
    1342
    +   -- because it is mentioned in the error message itself
    
    1343
    +
    
    1344
    +      ExprWithTySig _ (L _ e') _
    
    1345
    +        | XExpr (ExpandedThingRn o _) <- e' -> addExpansionErrCtxt o (ExprCtxt e) thing_inside
    
    1346
    +   -- There is a special case for expressions with signatures to avoid having too verbose
    
    1347
    +   -- error context. So here we flip the ErrCtxt state to expanded if the expression is expanded.
    
    1348
    +   -- c.f. RecordDotSyntaxFail9
    
    1349
    +
    
    1350
    +      XExpr (ExpandedThingRn o _) -> addExpansionErrCtxt o (srcCodeOriginErrCtxMsg o) thing_inside
    
    1351
    +   -- Flip error ctxt into expansion mode
    
    1352
    +
    
    1353
    +      _ -> addErrCtxt (ExprCtxt e) thing_inside
    
    1354
    +
    
    1355
    +
    
    1327 1356
     getErrCtxt :: TcM [ErrCtxt]
    
    1328 1357
     getErrCtxt = do { env <- getLclEnv; return (getLclEnvErrCtxt env) }
    
    1329 1358
     
    
    ... ... @@ -1335,7 +1364,7 @@ setErrCtxt ctxt = updLclEnv (setLclEnvErrCtxt ctxt)
    1335 1364
     -- do any tidying.
    
    1336 1365
     -- See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr
    
    1337 1366
     addErrCtxt :: ErrCtxtMsg -> TcM a -> TcM a
    
    1338
    -{-# INLINE addErrCtxt #-}   -- Note [Inlining addErrCtxt]
    
    1367
    +o{-# INLINE addErrCtxt #-}   -- Note [Inlining addErrCtxt]
    
    1339 1368
     addErrCtxt msg = addErrCtxtM (\env -> return (env, msg))
    
    1340 1369
     
    
    1341 1370
     -- See Note [ErrCtxtStack Manipulation]