[Git][ghc/ghc][wip/expand-do] fixes for Note [Expanding HsDo with HsExpansion]
Apoorv Ingle (@ani)
gitlab at gitlab.haskell.org
Mon Sep 18 01:35:08 UTC 2023
Apoorv Ingle pushed to branch wip/expand-do at Glasgow Haskell Compiler / GHC
Commits:
9d886038 by Apoorv Ingle at 2023-09-17T20:33:30-05:00
fixes for Note [Expanding HsDo with HsExpansion]
- - - - -
1 changed file:
- compiler/GHC/Tc/Gen/Match.hs
Changes:
=====================================
compiler/GHC/Tc/Gen/Match.hs
=====================================
@@ -1391,14 +1391,14 @@ 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 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
+We expand `do` blocks before typechecking it rather than after type checking it using the
+`HsExpansions` similar to `HsIf` with rebindable syntax and `RecordSyntax`.
+The case in point to implement this is to make impredicativity work well with
+with bind statement expression. See #18324, #23147, #15598, #22086, #22788
-Consider a do expression written in by the user
+Consider a `do` block written by the user
- f = {l0} do {l1} p <- {l1'}e1
+ f = {l0} do {l1} {pl}p <- {l1'}e1
{l2} g p
{l3} return {l3'}p
@@ -1407,24 +1407,28 @@ The {l1} etc are location/source span information stored in the AST,
The expanded version (performed by expand_do_stmts) looks as follows:
- f = {g1} (>>=) ({l1'} e1) (\ p ->
+ f = {g1} (>>=) ({l1'} e1) (\ {pl}p ->
{g2} (>>) ({l2} g p)
({l3} return p))
+We do this expansion in Tc.Gen.Match and not in Rename.Expr because we may not have
+all the information populated in the `RnM` monad also, not all the type variables will be
+in scope with -XTypeApplications is turned on (c.f. )
+
The 3 main points to consider are:
-1. Decorate an expression a fail block if the pattern match is not irrefutable
-2. Generate appropriate warnings for discarded results in a body statement eg. say g p :: m Int
+1. Decorate the expression with a `fail` block if the pattern match is not irrefutable
+2. Generate appropriate warnings for discarded results in a body statement eg. say `g p :: m Int`
3. Generating appropriate type error messages that blame the correct source spans
Part 1. Decorate failable patterns with fail blocks
---------------------------------------------------
-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
+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
-(approximately) will be
+(ignoring the location information) will be
(>>=)
(e1)
@@ -1432,27 +1436,28 @@ For example, the expansion of the do block
\ p -> e2
_ -> fail "failable pattern p at location")
-Why an anonymous lambda?
-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.
+* Why an anonymous lambda?
+ 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.
* Wrinkle 1: For pattern synonyms (see testcase Typeable1.hs)
- We always decorate it with a fail block as the irrefutable pattern checker returns false
+ 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
-* Wrinkle 2: MonadFail arising due to generated `fail` statements. (See testcase MonadFailErrors.hs)
+* Wrinkle 2: `MonadFail` arising 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. So we decorate the fail alternative expression with a `ExpandedPat`
that tags the fail expression with the failable pattern.
Part 2. Generate warnings for discarded body statement results
--------------------------------------------------------------
-If the do blocks body statement is an expression that returns a
-value which is not Unit aka (), then we need to warn the user when -Wunused-binds flag is turned on
+If the `do` blocks' body statement is an expression that returns a
+value that is not Unit aka (), then we need to warn the user about discarded
+value when -Wunused-binds flag is turned on
(See testcase T3263-2.hs)
For example the do expression
@@ -1464,9 +1469,10 @@ 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`
+now if `e1` returns a non-() value then we emit a warning. This check is done during desugaring
+`HsToCore.dsExpr` for the `HsApp` case calls `warnUnusedBindValue`
The decision function to trigger the warning is if the function is a `>>` and it is a compiler generated
+and e1 is a non-() value
Part 3. Blaming offending source code and Generating Appropriate Error Messages
-------------------------------------------------------------------------------
@@ -1492,18 +1498,17 @@ expands to
{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
+Whenever the typechecker steps through and `ExpandedStmt`,
+we push the original statement in the error context and typecheck 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]
+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
+we need to first pop the top of the error context which contains the error message for the previous statement:
"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.
@@ -1528,19 +1533,19 @@ expands to
}
-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
+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.
+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 a `DoExpansionOrigin`.
-Part 4. Compiling ExpandedStmts
--------------------------------
+Part 4. Compiling `ExpandedStmts` to `ExpansionStmts`
+----------------------------------------------------
Certain checks like warn unused binds, incomplete pattern match etc (cf. examples)
are performed on the core rather than on surface syntax. To ensure we produce warnings
-at the appropriate source code, we compile (ExpandedStmt stmt exp) to ExpansionStmt stmt exp'
+at the appropriate source code, we compile (ExpandedStmt stmt exp) to `ExpansionStmt` stmt exp'
where exp' is the typechecked version of exp, the expansion expression. This is very similar
-to the original HsExpansion flow.
-The work of convering `ExpandedStmt` to `ExpansionStmt` is done by `GHC.Gen.Head.rebuildHsApps`
+to the original `HsExpansion` flow. The work of convering `ExpandedStmt` to `ExpansionStmt`
+is done by `GHC.Gen.Head.rebuildHsApps`
-}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9d886038287891315b4f74ebb0fd771caba09e54
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9d886038287891315b4f74ebb0fd771caba09e54
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/20230917/272fcf63/attachment-0001.html>
More information about the ghc-commits
mailing list