Simon Peyton Jones pushed to branch wip/ani/better-expansion at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • compiler/GHC/Tc/Gen/App.hs
    ... ... @@ -656,8 +656,8 @@ tcInstFun :: QLFlag
    656 656
               -> TcSigmaType -> [HsExprArg 'TcpRn]
    
    657 657
               -> TcM ( [HsExprArg 'TcpInst]
    
    658 658
                      , TcSigmaType )   -- Does not instantiate trailing invisible foralls
    
    659
    --- This crucial function implements the |-inst judgement in Fig 4, plus the
    
    660
    --- modification in Fig 5, of the QL paper:
    
    659
    +-- This crucial function implements the |-inst judgement in Fig 4,
    
    660
    +-- plus the modification in Fig 5, of the QL paper:
    
    661 661
     -- "A quick look at impredicativity" (ICFP'20).
    
    662 662
     tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    
    663 663
       = do { traceTc "tcInstFun" (vcat [ text "tc_fun" <+> ppr tc_fun
    
    ... ... @@ -665,7 +665,8 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    665 665
                                        , text "fun_sigma" <+> ppr fun_sigma
    
    666 666
                                        , text "args:" <+> ppr rn_args
    
    667 667
                                        , text "do_ql" <+> ppr do_ql])
    
    668
    -       ; res@(_, fun_ty) <- go 1 [] fun_sigma rn_args
    
    668
    +       ; fun_origin <- mk_origin rn_head
    
    669
    +       ; res@(_, fun_ty) <- go fun_origin 1 [] fun_sigma rn_args
    
    669 670
            ; traceTc "tcInstFun:ret" (ppr fun_ty)
    
    670 671
            ; return res
    
    671 672
            }
    
    ... ... @@ -683,7 +684,7 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    683 684
          = return $ exprCtOrigin rn_fun
    
    684 685
     
    
    685 686
          | otherwise -- If the location is generated, the best we can do is to
    
    686
    -                -- approximate by looking on top of the error message stack
    
    687
    +                 -- approximate by looking on top of the error message stack
    
    687 688
          = do { err_ctxt_stack <- getErrCtxt
    
    688 689
               ; let hs_ctxt = case err_ctxt_stack of
    
    689 690
                                  (c:_) -> c
    
    ... ... @@ -692,8 +693,6 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    692 693
               ; return $ hsCtxtCtOrigin hs_ctxt
    
    693 694
               }
    
    694 695
     
    
    695
    -
    
    696
    -
    
    697 696
         -- These are the type variables which must be instantiated to concrete
    
    698 697
         -- types. See Note [Representation-polymorphic Ids with no binding]
    
    699 698
         -- in GHC.Tc.Utils.Concrete
    
    ... ... @@ -725,34 +724,35 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    725 724
         inst_fun _                = isInferredForAllTyFlag
    
    726 725
     
    
    727 726
         -----------
    
    728
    -    go, go1 :: Int                      -- Value-argument position of next arg
    
    727
    +    go, go1 :: CtOrigin                 -- Of the function
    
    728
    +            -> Int                      -- Value-argument position of next arg
    
    729 729
                 -> [HsExprArg 'TcpInst]     -- Accumulator, reversed
    
    730 730
                 -> TcSigmaType -> [HsExprArg 'TcpRn]
    
    731 731
                 -> TcM ([HsExprArg 'TcpInst], TcSigmaType)
    
    732 732
     
    
    733 733
         -- go: If fun_ty=kappa, look it up in Theta
    
    734
    -    go pos acc fun_ty args
    
    734
    +    go fun_orig pos acc fun_ty args
    
    735 735
           | Just kappa <- getTyVar_maybe fun_ty
    
    736 736
           , isQLInstTyVar kappa
    
    737 737
           = do { cts <- readMetaTyVar kappa
    
    738 738
                ; case cts of
    
    739
    -                Indirect fun_ty' -> go  pos acc fun_ty' args
    
    740
    -                Flexi            -> go1 pos acc fun_ty  args }
    
    739
    +                Indirect fun_ty' -> go  fun_orig pos acc fun_ty' args
    
    740
    +                Flexi            -> go1 fun_orig pos acc fun_ty  args }
    
    741 741
          | otherwise
    
    742
    -     = go1 pos acc fun_ty args
    
    742
    +     = go1 fun_orig pos acc fun_ty args
    
    743 743
     
    
    744 744
         -- go1: fun_ty is not filled-in instantiation variable
    
    745 745
         --      ('go' dealt with that case)
    
    746 746
     
    
    747 747
         -- Handle out-of-scope functions gracefully
    
    748
    -    go1 pos acc fun_ty (arg : rest_args)
    
    748
    +    go1 fun_orig pos acc fun_ty (arg : rest_args)
    
    749 749
           | fun_is_out_of_scope, looks_like_type_arg arg   -- See Note [VTA for out-of-scope functions]
    
    750
    -      = go pos acc fun_ty rest_args
    
    750
    +      = go fun_orig pos acc fun_ty rest_args
    
    751 751
     
    
    752 752
         -- Rule IALL from Fig 4 of the QL paper; applies even if args = []
    
    753 753
         -- Instantiate invisible foralls and dictionaries.
    
    754 754
         -- c.f. GHC.Tc.Utils.Instantiate.topInstantiate
    
    755
    -    go1 pos acc fun_ty args
    
    755
    +    go1 fun_orig pos acc fun_ty args
    
    756 756
           | (tvs,   body1) <- tcSplitSomeForAllTyVars (inst_fun args) fun_ty
    
    757 757
           , (theta, body2) <- if inst_fun args Inferred
    
    758 758
                               then tcSplitPhiTy body1
    
    ... ... @@ -763,8 +763,7 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    763 763
           , let no_tvs   = null tvs
    
    764 764
                 no_theta = null theta
    
    765 765
           , not (no_tvs && no_theta)
    
    766
    -      = do { fun_orig <- mk_origin rn_head
    
    767
    -           ; (wrap, fun_rho) <-
    
    766
    +      = do { (wrap, fun_rho) <-
    
    768 767
                     -- addHeadCtxt: important for the class constraints
    
    769 768
                     -- that may be emitted from instantiating fun_sigma
    
    770 769
                     setSrcSpan fun_lspan $
    
    ... ... @@ -782,12 +781,12 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    782 781
                       -- argument of (#,#) to @LiftedRep, but want to rule out the
    
    783 782
                       -- second instantiation @r.
    
    784 783
     
    
    785
    -           ; go pos (addArgWrap wrap acc) fun_rho args }
    
    784
    +           ; go fun_orig pos (addArgWrap wrap acc) fun_rho args }
    
    786 785
                     -- Going around again means we deal easily with
    
    787 786
                     -- nested  forall a. Eq a => forall b. Show b => blah
    
    788 787
     
    
    789 788
         -- Rule IRESULT from Fig 4 of the QL paper; no more arguments
    
    790
    -    go1 _pos acc fun_ty []
    
    789
    +    go1 _fun_orig _pos acc fun_ty []
    
    791 790
            | XExpr (ConLikeTc (RealDataCon dc)) <- tc_fun
    
    792 791
            , isNewDataCon dc
    
    793 792
            , [Scaled _ orig_arg_ty] <- dataConOrigArgTys dc
    
    ... ... @@ -807,30 +806,30 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    807 806
           = return (reverse acc, fun_ty)
    
    808 807
     
    
    809 808
         -- Rule ITVDQ from the GHC Proposal #281
    
    810
    -    go1 pos acc fun_ty ((EValArg { ea_arg = arg }) : rest_args)
    
    809
    +    go1 fun_orig pos acc fun_ty ((EValArg { ea_arg = arg }) : rest_args)
    
    811 810
           | Just (tvb, body) <- tcSplitForAllTyVarBinder_maybe fun_ty
    
    812 811
           = assertPpr (binderFlag tvb == Required) (ppr fun_ty $$ ppr arg) $
    
    813 812
             -- Any invisible binders have been instantiated by IALL above,
    
    814 813
             -- so this forall must be visible (i.e. Required)
    
    815 814
             do { (ty_arg, inst_body) <- tcVDQ fun_conc_tvs (tvb, body) arg
    
    816 815
                ; let wrap = mkWpTyApps [ty_arg]
    
    817
    -           ; go (pos+1) (addArgWrap wrap acc) inst_body rest_args }
    
    816
    +           ; go fun_orig (pos+1) (addArgWrap wrap acc) inst_body rest_args }
    
    818 817
     
    
    819
    -    go1 pos acc fun_ty (EWrap w : args)
    
    820
    -      = go1 pos (EWrap w : acc) fun_ty args
    
    818
    +    go1 fun_orig pos acc fun_ty (EWrap w : args)
    
    819
    +      = go1 fun_orig pos (EWrap w : acc) fun_ty args
    
    821 820
     
    
    822
    -    go1 pos acc fun_ty (EPrag sp prag : args)
    
    823
    -      = go1 pos (EPrag sp prag : acc) fun_ty args
    
    821
    +    go1 fun_orig pos acc fun_ty (EPrag sp prag : args)
    
    822
    +      = go1 fun_orig pos (EPrag sp prag : acc) fun_ty args
    
    824 823
     
    
    825 824
         -- Rule ITYARG from Fig 4 of the QL paper
    
    826
    -    go1 pos acc fun_ty ( ETypeArg { ea_loc_span = ctxt, ea_hs_ty = hs_ty }
    
    827
    -                             : rest_args )
    
    825
    +    go1 fun_orig pos acc fun_ty ( ETypeArg { ea_loc_span = ctxt, ea_hs_ty = hs_ty }
    
    826
    +                                  : rest_args )
    
    828 827
           = do { (ty_arg, inst_ty) <- tcVTA fun_conc_tvs fun_ty hs_ty
    
    829 828
                ; let arg' = ETypeArg { ea_loc_span = ctxt, ea_hs_ty = hs_ty, ea_ty_arg = ty_arg }
    
    830
    -           ; go pos (arg' : acc) inst_ty rest_args }
    
    829
    +           ; go fun_orig pos (arg' : acc) inst_ty rest_args }
    
    831 830
     
    
    832 831
         -- Rule IVAR from Fig 4 of the QL paper:
    
    833
    -    go1 pos acc fun_ty args@(EValArg {} : _)
    
    832
    +    go1 fun_orig pos acc fun_ty args@(EValArg {} : _)
    
    834 833
           | Just kappa <- getTyVar_maybe fun_ty
    
    835 834
           , isQLInstTyVar kappa
    
    836 835
           = -- Function type was of form   f :: forall a b. t1 -> t2 -> b
    
    ... ... @@ -846,7 +845,7 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    846 845
             --   - We must be sure to actually update the variable right now,
    
    847 846
             --     not defer in any way, because this is a QL instantiation variable.
    
    848 847
             -- It's easier just to do the job directly here.
    
    849
    -        do { arg_tys <- zipWithM new_arg_ty (leadingValArgs args) [pos..]
    
    848
    +        do { arg_tys <- zipWithM (new_arg_ty fun_orig) (leadingValArgs args) [pos..]
    
    850 849
                ; res_ty  <- newOpenFlexiTyVarTyQL do_ql TauTv
    
    851 850
                ; let fun_ty' = mkScaledFunTys arg_tys res_ty
    
    852 851
     
    
    ... ... @@ -862,13 +861,12 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    862 861
                      -- Then fun_ty :: kk, fun_ty' :: Type, kind_co :: Type ~ kk
    
    863 862
                      --      co_wrap :: (fun_ty' |> kind_co) ~ fun_ty'
    
    864 863
     
    
    865
    -           ; go pos acc' fun_ty' args }
    
    864
    +           ; go fun_orig pos acc' fun_ty' args }
    
    866 865
     
    
    867 866
         -- Rule IARG from Fig 4 of the QL paper:
    
    868
    -    go1 pos acc fun_ty
    
    867
    +    go1 fun_orig pos acc fun_ty
    
    869 868
             (EValArg { ea_arg = arg, ea_loc_span = ctxt } : rest_args)
    
    870
    -      = do { fun_orig <- mk_origin rn_head
    
    871
    -           ; let herald = mk_herald fun_orig tc_fun (unLoc arg)
    
    869
    +      = do { let herald = mk_herald fun_orig tc_fun (unLoc arg)
    
    872 870
                ; (fun_co, arg_ty, res_ty) <-
    
    873 871
                     -- NB: matchActualFunTy does the rep-poly check.
    
    874 872
                     -- For example, suppose we have f :: forall r (a::TYPE r). a -> Int
    
    ... ... @@ -882,13 +880,12 @@ tcInstFun do_ql inst_final rn_head@(_, fun_lspan) tc_fun fun_sigma rn_args
    882 880
                       (n_val_args, fun_sigma) fun_ty
    
    883 881
                ; arg' <- quickLookArg do_ql pos ctxt rn_head arg arg_ty
    
    884 882
                ; let acc' = arg' : addArgWrap (mkWpCastN fun_co) acc
    
    885
    -           ; go (pos+1) acc' res_ty rest_args }
    
    883
    +           ; go fun_orig (pos+1) acc' res_ty rest_args }
    
    886 884
     
    
    887
    -    new_arg_ty :: LHsExpr GhcRn -> Int -> TcM (Scaled TcType)
    
    885
    +    new_arg_ty :: CtOrigin -> LHsExpr GhcRn -> Int -> TcM (Scaled TcType)
    
    888 886
         -- Make a fresh nus for each argument in rule IVAR
    
    889
    -    new_arg_ty (L _ arg) i
    
    890
    -      = do { fun_orig <- mk_origin rn_head
    
    891
    -           ; arg_nu <- newArgTyVarTyQL do_ql $
    
    887
    +    new_arg_ty fun_orig (L _ arg) i
    
    888
    +      = do { arg_nu <- newArgTyVarTyQL do_ql $
    
    892 889
                            FRRExpectedFunTy (mk_herald fun_orig tc_fun arg) i
    
    893 890
                    -- Following matchActualFunTy, we create nu_i :: TYPE kappa_i[conc],
    
    894 891
                    -- thereby ensuring that the arguments have concrete runtime representations
    

  • compiler/GHC/Tc/Gen/Expand.hs
    1
    +{-# LANGUAGE TypeFamilies        #-}
    
    2
    +
    
    3
    +{-
    
    4
    +(c) The University of Glasgow 2006
    
    5
    +(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
    
    6
    +-}
    
    7
    +
    
    8
    +module GHC.Tc.Gen.Expand( tcExpand ) where
    
    9
    +
    
    10
    +import GHC.Prelude
    
    11
    +
    
    12
    +import {-# SOURCE #-} GHC.Tc.Gen.Splice( getUntypedSpliceBody )
    
    13
    +
    
    14
    +import GHC.Hs
    
    15
    +
    
    16
    +import GHC.Tc.Utils.Monad
    
    17
    +import GHC.Tc.Types.ErrCtxt
    
    18
    +
    
    19
    +import GHC.Rename.Utils
    
    20
    +
    
    21
    +import GHC.Types.SrcLoc
    
    22
    +
    
    23
    +
    
    24
    +{- Note [Typechecking by expansion: overview]
    
    25
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    26
    +For many constructs, rather than typechecking the user-written code
    
    27
    +directly, it's much easier to
    
    28
    +   * Expand (or desugar) the code to something simpler
    
    29
    +   * Typecheck that simpler expression
    
    30
    +
    
    31
    +Example: Typechecking the do expression. The typechecker looks (somewhat) like this:
    
    32
    +
    
    33
    +   tcExpr e@(HsDo _ stmts) rho = do { hse <- expandDoStmts stmts
    
    34
    +                                    ; tcHsExpansion hse rho }
    
    35
    +
    
    36
    +The `expandDoStmts` replaces the HsDo { x <- e1; return x }
    
    37
    +with something like
    
    38
    +   HSE { hse_ctxt = ExprCtxt e
    
    39
    +       , hse_exp  = e1 >>= \ x -> x }
    
    40
    +and we then typecheck the expression `e1 >>= \ x -> x`
    
    41
    +
    
    42
    +See also Note [Handling overloaded and rebindable constructs]
    
    43
    +     and Note [Doing XXExprGhcRn in the Renamer vs Typechecker]
    
    44
    +
    
    45
    +The Big Question is how to ensure that error messages mention
    
    46
    +only user-written source code, and never talk about the expanded code.
    
    47
    +The rest of this Note explains how that is done.
    
    48
    +
    
    49
    +* The expansion process typically takes a user written thing
    
    50
    +       L lspan ue
    
    51
    +  and returns
    
    52
    +       L lspan (XExpr (ExpandedThingRn (HSE { hse_ctxt = ue
    
    53
    +                                            , hse_exp  = ee } ))
    
    54
    +  where `ee` is the expansion of the user written thing `ue`
    
    55
    +
    
    56
    +* The type checker context has 3 key fields that describe the context:
    
    57
    +     TcLclCtxt { tcl_loc         :: RealSrcSpan
    
    58
    +               , tcl_in_gen_code :: Bool
    
    59
    +               , tcl_err_ctxt    :: ErrCtxtStack
    
    60
    +               , ... }
    
    61
    +  Note `tcl_loc` always points to a real place in the source code,
    
    62
    +  hence `RealSrcSpan`.
    
    63
    +
    
    64
    +  The `tcl_err_ctxt` is a stack of contexts, each saying something
    
    65
    +  like "In the expression: x+y" or "In second argument of `$` namely 'r { x=2 }'"
    
    66
    +
    
    67
    +  The `tcl_in_gen_code` is a boolean that keeps track of whether
    
    68
    +  the current expression being typechecked is compiler generated
    
    69
    +  or user generated.
    
    70
    +
    
    71
    +  INVARIANT: `tcl_loc` and `tcl_in_gen_code` are modified only in `setSrcSpan`.
    
    72
    +
    
    73
    +* Now, when
    
    74
    +      tcMonoLExpr :: LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    75
    +  gets a located expression, it does 3 things:
    
    76
    +    (a) Calls `setSrcSpanA` to set the ambient source-code location
    
    77
    +    (b) Calls `addExprCtxt` to push a suitable `HsCtxt` on top of the `tcl_err_ctxt`.
    
    78
    +    (c) Calls `tcExpr` to typecheck the expression.
    
    79
    +
    
    80
    +* In these calls, if the `span` is generated  (see `isGeneratedSrcSpan`), then
    
    81
    +     - `setSrcSpanA` sets `tcl_in_gen_code` to `True`, and leaves `tcl_loc` unchanged
    
    82
    +     - `addExprCtxt` is a no-op if `tcl_in_gen_code` is True
    
    83
    +  The result is that `tcl_loc` has the span from the innermost /user/ tree node;
    
    84
    +  and the ErrCtxtStack in `tcl_err_ctxt` only has contexts arisign from user code.
    
    85
    +
    
    86
    +* Note that inside an expansion we have sub-expressions from the original program.
    
    87
    +  As soon as we enter one of those, identified by a /user/ span, `setSrcSpanA` will
    
    88
    +  sets the `tcl_loc` to reflect that span, and switch off `tcl_in_gen_code`.  Nice!
    
    89
    +-}
    
    90
    +
    
    91
    +---------------
    
    92
    +tcExpand :: HsExpr GhcRn -> TcM (Maybe (HsExpansion GhcRn))
    
    93
    +tcExpand e@(OpApp _ arg1 op arg2)
    
    94
    +  = return $ Just $
    
    95
    +    HSE { hse_ctxt = ExprCtxt e
    
    96
    +        , hse_exp  = foldl ap op [arg1,arg2] }
    
    97
    +  where
    
    98
    +    ap f a = wrapGenSpan (HsApp noExtField f a)
    
    99
    +
    
    100
    +tcExpand (XExpr (ExpandedThingRn hse))
    
    101
    +  = return (Just hse)
    
    102
    +
    
    103
    +tcExpand e@(HsUntypedSplice splice_res _)
    
    104
    +-- See Note [Looking through Template Haskell splices in splitHsApps]
    
    105
    +  = do { fun <- getUntypedSpliceBody splice_res
    
    106
    +       ; return $ Just $
    
    107
    +         HSE { hse_ctxt = ExprCtxt e          -- ToDo: right?
    
    108
    +             , hse_exp  = L noSrcSpanA fun } } -- Span?
    
    109
    +{-
    
    110
    +      where
    
    111
    +        lspan' :: SrcSpan
    
    112
    +        lspan' = case splice of
    
    113
    +            HsUntypedSpliceExpr _ (L l _) -> locA l -- l :: SrcAnn AnnListItem
    
    114
    +            HsQuasiQuote _ _ (L l _)      -> locA l -- l :: SrcAnn NoEpAnns
    
    115
    +            (XUntypedSplice (HsImplicitLiftSplice _ _ _ (L l _))) -> locA l
    
    116
    +-}
    
    117
    +
    
    118
    +tcExpand _ = return Nothing

  • compiler/GHC/Tc/Gen/Expr.hs
    ... ... @@ -19,7 +19,6 @@ module GHC.Tc.Gen.Expr
    19 19
              tcInferRhoFRR, tcInferRhoFRRNC,
    
    20 20
              tcPolyLExpr,  tcPolyLExprSig, tcPolyLExprNC,
    
    21 21
              tcPolyExpr, tcExpr,
    
    22
    -         tcExpand,
    
    23 22
              tcSyntaxOp, tcSyntaxOpGen, SyntaxOpType(..), synKnownType,
    
    24 23
              tcCheckId,
    
    25 24
              ) where
    
    ... ... @@ -31,10 +30,10 @@ import {-# SOURCE #-} GHC.Tc.Gen.Splice
    31 30
     
    
    32 31
     import GHC.Hs
    
    33 32
     import GHC.Hs.Syn.Type
    
    34
    -
    
    35 33
     import GHC.Rename.Utils
    
    36 34
     import GHC.Rename.Env         ( addUsedGRE, getUpdFieldLbls )
    
    37 35
     
    
    36
    +import GHC.Tc.Gen.Expand( tcExpand )
    
    38 37
     import GHC.Tc.Gen.App
    
    39 38
     import GHC.Tc.Gen.Head
    
    40 39
     import GHC.Tc.Gen.Do
    
    ... ... @@ -770,73 +769,6 @@ tcExpr e res_ty
    770 769
     ************************************************************************
    
    771 770
     -}
    
    772 771
     
    
    773
    -{- Note [Typechecking by expansion: overview]
    
    774
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    775
    -For many constructs, rather than typechecking the user-written code
    
    776
    -directly, it's much easier to
    
    777
    -   * Expand (or desugar) the code to something simpler
    
    778
    -   * Typecheck that simpler expression
    
    779
    -
    
    780
    -Example: Typechecking the do expression. The typechecker looks (somewhat) like this:
    
    781
    -
    
    782
    -   tcExpr e@(HsDo _ stmts) rho = do { hse <- expandDoStmts stmts
    
    783
    -                                    ; tcHsExpansion hse rho }
    
    784
    -
    
    785
    -The `expandDoStmts` replaces the HsDo { x <- e1; return x }
    
    786
    -with something like
    
    787
    -   HSE { hse_ctxt = ExprCtxt e
    
    788
    -       , hse_exp  = e1 >>= \ x -> x }
    
    789
    -and we then typecheck the expression `e1 >>= \ x -> x`
    
    790
    -
    
    791
    -See also Note [Handling overloaded and rebindable constructs]
    
    792
    -     and Note [Doing XXExprGhcRn in the Renamer vs Typechecker]
    
    793
    -
    
    794
    -The Big Question is how to ensure that error messages mention
    
    795
    -only user-written source code, and never talk about the expanded code.
    
    796
    -The rest of this Note explains how that is done.
    
    797
    -
    
    798
    -* The expansion process typically takes a user written thing
    
    799
    -       L lspan ue
    
    800
    -  and returns
    
    801
    -       L lspan (XExpr (ExpandedThingRn (HSE { hse_ctxt = ue
    
    802
    -                                            , hse_exp  = ee } ))
    
    803
    -  where `ee` is the expansion of the user written thing `ue`
    
    804
    -
    
    805
    -* The type checker context has 3 key fields that describe the context:
    
    806
    -     TcLclCtxt { tcl_loc         :: RealSrcSpan
    
    807
    -               , tcl_in_gen_code :: Bool
    
    808
    -               , tcl_err_ctxt    :: ErrCtxtStack
    
    809
    -               , ... }
    
    810
    -  Note `tcl_loc` always points to a real place in the source code,
    
    811
    -  hence `RealSrcSpan`.
    
    812
    -
    
    813
    -  The `tcl_err_ctxt` is a stack of contexts, each saying something
    
    814
    -  like "In the expression: x+y" or "In second argument of `$` namely 'r { x=2 }'"
    
    815
    -
    
    816
    -  The `tcl_in_gen_code` is a boolean that keeps track of whether
    
    817
    -  the current expression being typechecked is compiler generated
    
    818
    -  or user generated.
    
    819
    -
    
    820
    -  INVARIANT: `tcl_loc` and `tcl_in_gen_code` are modified only in `setSrcSpan`.
    
    821
    -
    
    822
    -* Now, when
    
    823
    -      tcMonoLExpr :: LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    824
    -  gets a located expression, it does 3 things:
    
    825
    -    (a) Calls `setSrcSpanA` to set the ambient source-code location
    
    826
    -    (b) Calls `addExprCtxt` to push a suitable `HsCtxt` on top of the `tcl_err_ctxt`.
    
    827
    -    (c) Calls `tcExpr` to typecheck the expression.
    
    828
    -
    
    829
    -* In these calls, if the `span` is generated  (see `isGeneratedSrcSpan`), then
    
    830
    -     - `setSrcSpanA` sets `tcl_in_gen_code` to `True`, and leaves `tcl_loc` unchanged
    
    831
    -     - `addExprCtxt` is a no-op if `tcl_in_gen_code` is True
    
    832
    -  The result is that `tcl_loc` has the span from the innermost /user/ tree node;
    
    833
    -  and the ErrCtxtStack in `tcl_err_ctxt` only has contexts arisign from user code.
    
    834
    -
    
    835
    -* Note that inside an expansion we have sub-expressions from the original program.
    
    836
    -  As soon as we enter one of those, identified by a /user/ span, `setSrcSpanA` will
    
    837
    -  sets the `tcl_loc` to reflect that span, and switch off `tcl_in_gen_code`.  Nice!
    
    838
    --}
    
    839
    -
    
    840 772
     tcHsExpansion :: HsExpansion GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)
    
    841 773
     tcHsExpansion (HSE { hse_ctxt = o, hse_exp = e }) res_ty
    
    842 774
        = do { e' <- tcMonoLExpr e res_ty
    
    ... ... @@ -844,31 +776,6 @@ tcHsExpansion (HSE { hse_ctxt = o, hse_exp = e }) res_ty
    844 776
               HSE { hse_ctxt = o, hse_exp = e' } }
    
    845 777
     
    
    846 778
     
    
    847
    ----------------
    
    848
    -tcExpand :: HsExpr GhcRn -> TcM (Maybe (HsExpansion GhcRn))
    
    849
    -tcExpand e@(OpApp _ arg1 op arg2)
    
    850
    -  = return (Just (HSE { hse_ctxt = ExprCtxt e
    
    851
    -                      , hse_exp  = wrapGenSpan (unLoc $ mkHsApps op [arg1,arg2]) }))
    
    852
    -tcExpand (XExpr (ExpandedThingRn hse))
    
    853
    -  = return (Just hse)
    
    854
    -
    
    855
    -tcExpand e@(HsUntypedSplice splice_res _)
    
    856
    --- See Note [Looking through Template Haskell splices in splitHsApps]
    
    857
    -  = do { fun <- getUntypedSpliceBody splice_res
    
    858
    -       ; return $ Just $
    
    859
    -         HSE { hse_ctxt = ExprCtxt e          -- ToDo: right?
    
    860
    -             , hse_exp  = L noSrcSpanA fun } } -- Span?
    
    861
    -{-
    
    862
    -      where
    
    863
    -        lspan' :: SrcSpan
    
    864
    -        lspan' = case splice of
    
    865
    -            HsUntypedSpliceExpr _ (L l _) -> locA l -- l :: SrcAnn AnnListItem
    
    866
    -            HsQuasiQuote _ _ (L l _)      -> locA l -- l :: SrcAnn NoEpAnns
    
    867
    -            (XUntypedSplice (HsImplicitLiftSplice _ _ _ (L l _))) -> locA l
    
    868
    --}
    
    869
    -
    
    870
    -tcExpand _ = return Nothing
    
    871
    -
    
    872 779
     {-
    
    873 780
     ************************************************************************
    
    874 781
     *                                                                      *
    

  • compiler/GHC/Tc/Gen/Expr.hs-boot
    ... ... @@ -9,7 +9,6 @@ import GHC.Tc.Types.BasicTypes( TcCompleteSig )
    9 9
     import GHC.Tc.Types.Origin ( CtOrigin, FixedRuntimeRepContext )
    
    10 10
     import GHC.Core.Type ( Mult )
    
    11 11
     import GHC.Hs.Extension ( GhcRn, GhcTc )
    
    12
    -import Data.Maybe( Maybe )
    
    13 12
     
    
    14 13
     tcCheckPolyExpr, tcCheckPolyExprNC ::
    
    15 14
               LHsExpr GhcRn
    
    ... ... @@ -40,8 +39,6 @@ tcInferExprSigma :: HsExpr GhcRn -> TcM (HsExpr GhcTc, TcSigmaType)
    40 39
     
    
    41 40
     tcInferExpr :: InferInstFlag -> LHsExpr GhcRn -> TcM (LHsExpr GhcTc, TcType)
    
    42 41
     
    
    43
    -tcExpand :: HsExpr GhcRn -> TcM (Maybe (HsExpansion GhcRn))
    
    44
    -
    
    45 42
     tcSyntaxOp :: CtOrigin
    
    46 43
                -> SyntaxExprRn
    
    47 44
                -> [SyntaxOpType]           -- ^ shape of syntax operator arguments
    

  • compiler/GHC/Tc/Gen/Head.hs
    ... ... @@ -21,13 +21,14 @@ module GHC.Tc.Gen.Head
    21 21
     
    
    22 22
            , pprArgInst, addFunResCtxt ) where
    
    23 23
     
    
    24
    -import {-# SOURCE #-} GHC.Tc.Gen.Expr( tcExpr, tcExpand, tcCheckPolyExprNC, tcPolyLExprSig )
    
    24
    +import {-# SOURCE #-} GHC.Tc.Gen.Expr( tcExpr, tcCheckPolyExprNC, tcPolyLExprSig )
    
    25 25
     
    
    26 26
     import GHC.Prelude
    
    27 27
     import GHC.Hs
    
    28 28
     import GHC.Hs.Syn.Type
    
    29 29
     
    
    30 30
     import GHC.Tc.Gen.HsType
    
    31
    +import GHC.Tc.Gen.Expand( tcExpand )
    
    31 32
     import GHC.Tc.Gen.Bind( chooseInferredQuantifiers )
    
    32 33
     import GHC.Tc.Gen.Sig( tcUserTypeSig, tcInstSig )
    
    33 34
     import GHC.Tc.TyCl.PatSyn( patSynBuilderOcc )
    

  • compiler/ghc.cabal.in
    ... ... @@ -832,6 +832,7 @@ Library
    832 832
             GHC.Tc.Gen.Bind
    
    833 833
             GHC.Tc.Gen.Default
    
    834 834
             GHC.Tc.Gen.Do
    
    835
    +        GHC.Tc.Gen.Expand
    
    835 836
             GHC.Tc.Gen.Export
    
    836 837
             GHC.Tc.Gen.Expr
    
    837 838
             GHC.Tc.Gen.Foreign