Note [Doing XXExprGhcRn in the Renamer vs Typechecker]
We expand some `HsExpr GhcRn` code at various places, usually, on the fly,
depending on when it is more convenient. It may be beneficial to have a
separate `HsExpr GhcRn -> HsExpr GhcRn` pass that does this expansion uniformly
in the future when we have enough cases to cater for. For the time being,
this note documents which language feature is expanded at which phase,
and the reasons for doing so.
** `HsIf` Expansions
`HsIf` expansions are expanded in the Renamer becuase it is more convinent
to do so there and then not worry about it in the later stage.
`-XRebindableSyntax` is used to decide whether we use the `HsIf` or user defined if
** `OpApp` Expansions
The typechecker turns `OpApp` into a use of `XXExprGhcRn`
on the fly, in `GHC.Tc.Gen.Head.splitHsApps`.
The language extension `RebindableSyntax` does not affect this behaviour.
It's a bit painful to transform `OpApp e1 op e2` to a `XXExprGhcRn`
form, because the renamer does precedence rearrangement after name
resolution. So the renamer leaves an `OpApp` as an `OpApp`.
** Record Update Syntax `RecordUpd` Expansions
This is done in the typechecker on the fly (`GHC.Tc.Expr.tcExpr`), and not the renamer, for two reasons:
- (Until we implement GHC proposal #366)
We need to know the type of the record to disambiguate its fields.
- We use the type signature of the data constructor to provide `IdSigs`
to the let-bound variables (x', y' in the example of
Note [Handling overloaded and rebindable constructs] above).
This is needed to accept programs such as
data R b = MkR { f :: (forall a. a -> a) -> (Int,b), c :: Int }
foo r = r { f = \ k -> (k 3, k 'x') }
in which an updated field has a higher-rank type.
See Wrinkle [Using IdSig] in Note [Record Updates] in GHC.Tc.Gen.Expr.
** `HsDo` Statement Expansions
The expansion for do block statements is done on the fly right before typechecking in `GHC.Tc.Gen.Expr`
using `GHC.Tc.Gen.Do.expandDoStmts`. There are 2 main reasons:
- During the renaming phase, we may not have all the constructor details `HsConDetails` populated in the
data structure. This would result in an inaccurate irrefutability analysis causing
the continuation lambda body to be wrapped with `fail` alternatives when not needed.
See Part 1. of Note [Expanding HsDo with XXExprGhcRn] (test pattern-fails.hs)
- If the expansion is done on the fly during renaming, expressions that
have explicit type applications using (-XTypeApplciations) will not work (cf. Let statements expansion)
as the name freshening happens from the root of the AST to the leaves,
but the expansion happens in the opposite direction (from leaves to the root),
causing the renamer to miss the scoped type variables. References 3
- Handling overloaded and rebindable constructs GHC.Rename.Expr
- Expanding HsDo with XXExprGhcRn GHC.Tc.Gen.Do
- Record Updates GHC.Tc.Gen.Expr
Referenced by 4
- Handling overloaded and rebindable constructs GHC.Rename.Expr ×2
- GHC.Rename.Expr call site
- Expanding HsDo with XXExprGhcRn GHC.Tc.Gen.Do