[Git][ghc/ghc][wip/expand-do] adding Note and references
Apoorv Ingle (@ani)
gitlab at gitlab.haskell.org
Mon Aug 7 15:37:54 UTC 2023
Apoorv Ingle pushed to branch wip/expand-do at Glasgow Haskell Compiler / GHC
Commits:
2a6f531e by Apoorv Ingle at 2023-08-07T10:37:41-05:00
adding Note and references
- - - - -
5 changed files:
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Match.hs
- + compiler/GHC/Tc/Types/.#Origin.hs
- compiler/GHC/Types/Basic.hs
Changes:
=====================================
compiler/GHC/Hs/Expr.hs
=====================================
@@ -559,7 +559,7 @@ mkExpandedExprTc a b = XExpr (ExpansionExpr (HsExpanded a b))
-- The two components of the expansion are: original statement and
-- expanded typechecked expression.
mkExpandedStmtTc
- :: ExprLStmt GhcRn -- ^ source expression
+ :: ExprLStmt GhcRn -- ^ source expression
-> HsExpr GhcTc -- ^ expanded typechecked expression
-> HsExpr GhcTc -- ^ suitably wrapped 'HsExpansion'
mkExpandedStmtTc a b = XExpr (ExpansionStmt (HsExpanded a b))
=====================================
compiler/GHC/Tc/Gen/Expr.hs
=====================================
@@ -271,14 +271,16 @@ tcExpr (HsLam _ match) res_ty
= do { (wrap, match') <- tcMatchLambda herald match_ctxt match res_ty
; return (mkHsWrap wrap (HsLam noExtField match')) }
where
- match_ctxt | isDoExpansionGenerated (mg_ext match)
- = MC { mc_what = StmtCtxt (HsDoStmt (DoExpr Nothing))
- , mc_body = tcBodyNC -- NB: Do not add any error contexts
- -- It has already been done
- }
- | otherwise
- = MC { mc_what = LambdaExpr
- , mc_body = tcBody }
+ match_ctxt
+ | isDoExpansionGenerated (mg_ext match)
+ -- See Part 3. of Note [Expanding HsDo with HsExpansion]
+ = MC { mc_what = StmtCtxt (HsDoStmt (DoExpr Nothing))
+ , mc_body = tcBodyNC -- NB: Do not add any error contexts
+ -- It has already been done
+ }
+ | otherwise
+ = MC { mc_what = LambdaExpr
+ , mc_body = tcBody }
herald = ExpectedFunTyLam match
tcExpr e@(HsLamCase x lc_variant matches) res_ty
=====================================
compiler/GHC/Tc/Gen/Match.hs
=====================================
@@ -1386,9 +1386,9 @@ mk_fail_block _ _ _ = pprPanic "mk_fail_block: impossible happened" empty
{- Note [Expanding HsDo with HsExpansion]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We expand do blocks before typechecking it rather than after type checking it using the
-HsExpansions similar to HsIf expansions for rebindable syntax.
-The main reason to implement this is to make impredicatively typed expression statements typechec in do blocks.
-(#18324 and #23147).
+HsExpansions similar to HsIf with rebindable syntax and RecordSyntax.
+The main reason to implement this is to make impredicatively typed expression statements typecheck in do blocks.
+See #18324, #23147, #15598, #22086, #22788
Consider a do expression written in by the user
@@ -1412,33 +1412,36 @@ The 3 main points to consider are:
Part 1. Decorate failable patterns with fail blocks
---------------------------------------------------
-If p is a pattern that is failable
-the expansion of the statements
+If p is a pattern that is failable we need to decorate it with a fail block.
+For example, the expansion of the do block
do p <- e1
e2
-will be
+(approximately) will be
(>>=)
- e1
-
- / -- anonymous lambda
- \ p -> e
- _ -> fail "failable pattern p at location"
+ (e1)
+ (\case -- anonymous lambda case
+ \ p -> e2
+ _ -> fail "failable pattern p at location")
Why an anonymous lambda?
-A lambda is needed so as for the types to work out: this expression is a second
-argument to bind.
-And it is anonymous because we do not want to introduce a new name that will
+We need a lambda for the types to match: this expression is a second
+argument to bind so it needs to be of type `a -> m b`
+It is anonymous because we do not want to introduce a new name that will
never be seen by the user anyway.
-* Caveat: For pattern synonyms (see testcase Typeable1.hs)
-We always decorate it with a fail block. But then during desugaring
-we would get pattern match redundant warnings. To avoid such
-warnings we filter out those type patterns that appear in a do expansion generated match
+* Caveat 1: For pattern synonyms (see testcase Typeable1.hs)
+We always decorate it with a fail block as the irrefutable pattern checker returns false
+But then during desugaring we would then get pattern match redundant warnings. To avoid such
+spurious warnings we filter out those type patterns that appear in a do expansion generated match
in HsToCore.Match.matchWrapper
+* Caveat 2: MonadFail arrising due to generated `fail` statements. (See testcase MonadFailErrors.hs)
+In the error messages we need to say "pattern p" is failable so we need MonadFail and we are
+deep inside a generated code.
+
Part 2. Generate warnings for discarded body statement results
--------------------------------------------------------------
If the do blocks body statement is an expression that returns a
@@ -1455,23 +1458,76 @@ expands to
>> e1 e2
now if e1 returns a non-() value then we emit a warning. This check is done during desugaring
-HsToCore.dsExpr HsApp case calls warnUnusedBindValue
+HsToCore.dsExpr HsApp case calls `warnUnusedBindValue`
The decision function to trigger the warning is if the function is a `>>` and it is a compiler generated
-Part 3. Blaming Appropriate Code and Generating Appropriate Error Messages
---------------------------------------------------------------------------
+Part 3. Blaming offending source code and Generating Appropriate Error Messages
+-------------------------------------------------------------------------------
+To ensure we correctly track source of the offending
When we step through each of the do statements, we need to keep track of
-which statement expansion is the typechecker is currently typechecking.
-For this purpose we use the XXExprGhcRn.ExpandedStmt and XXExprGhcTc.ExpansionStmt
-The `ExpandedStmt` stores the original statement (with location) and the expanded expression
+which statement expansion the typechecker is currently typechecking.
+For this purpose we use the XXExprGhcRn.ExpandedStmt which
+stores the original statement (with location) and the expanded expression
+For example, the do expression
+ do e1
+ e2
-After typechecking a satement and before moving to the next statement,
+expands to
+
+ ExpandedExpr
+ (do e1 -- Original
+ e2) -- Statement
+ {ExpandedStmt e1 --
+ ({(>>) e1} -- Expanded
+ <PopErrCtxt> (ExpandedStmt e2 -- Expression
+ {e2})) --
+ }
+
+Whenever the typechecker steps through and ExpandedStmt,
+we push the origninal statement in the error context and type check the expanded expression.
+This is similar to vanilla HsExpansion and rebindable syntax
+See Note [Rebindable syntax and HsExpansion] in GHC.Hs.Expr.
+We associate the application ((>>) (e1)) with `ExpandedStmt` to ensure
+we do not mention compiler generated (>>) in
+the error context, rather when we typecheck the application, we push
+the "In the stmt of do block .." in the error context stack.
+See Note [splitHsApps]
+
+After a statement is typechecked and before moving to the next statement,
we need to first pop the top of the error context which contains the error message
-"In the statemen of a do block: p <- e".
+"In the stmt of a do block: e1".
This is explicitly encoded in the expansion expression using the `XXExprGhcRn.PopErrCtxt`.
-Whenever `tcExpr` encounters a PopErrCtxt it calls popErrCtxt to pop of the top of error context stack.
+Whenever `tcExpr` encounters a `PopErrCtxt` it calls `popErrCtxt` to pop of the top of error context stack.
+See <PopErrCtxt> in the example above.
+
+
+For example, the do expression with a bind statement
+
+ do p <- e1
+ e2
+
+expands to
+
+ ExpandedExpr
+ (do p <- e1 -- Original
+ e2 -- Statement
+ ) --
+ {ExpandedStmt (p <- e1) --
+ ({(>>=) e1} -- Expanded
+ <PopErrCtxt> (ExpandedStmt (e2) -- Expression
+ {\ p -> e2})) --
+ }
+
+
+However the expansion lambda (\ p -> e2) is special as it is generated from a do block expansion
+and if type checker error occurs in the pattern p, we need to say
+"in a pattern binding in a do block" and not "in a lambda abstraction" (cf. Typeable1.hs)
+hence we use a tag GenReason in Ghc.Tc.Origin. When typechecking a `HsLam` in Tc.Gen.Expr.tcExpr
+the match_ctxt is set to a StmtCtxt if GenOrigin is DoExpansion.
+
+
-}
=====================================
compiler/GHC/Tc/Types/.#Origin.hs
=====================================
@@ -0,0 +1 @@
+aningle at CS-M030.77677
\ No newline at end of file
=====================================
compiler/GHC/Types/Basic.hs
=====================================
@@ -597,8 +597,8 @@ isGenerated Generated {} = True
isGenerated FromSource = False
-- | Why was the piece of code generated?
---
--- See Note [Expanding HsDo with HsExpansion].
+-- It is useful for generating the right error context
+-- See Part 3 in Note [Expanding HsDo with HsExpansion]
data GenReason = DoExpansion
| OtherExpansion
deriving (Eq, Data)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2a6f531ec71f229f70ee1a542061e1fc16a89a01
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2a6f531ec71f229f70ee1a542061e1fc16a89a01
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230807/35c687d4/attachment-0001.html>
More information about the ghc-commits
mailing list