Draft: Another attempt at introducing hsExprType
Here is an attempt to implement hsExprType
using the power of the new XRec
extension point introduced in !3428 (closed).
This is largely based on the code from !2182 (closed).
I've slightly generalized HsWrap
and CoPat
to be pass polymorphic, so that can be converted to use non GHC passes. Without this, we would be unable to get the types of all subexpressions of something guarded by a HsWrap
.
I've also added a new type family NoGhcTcNonGhc
to allow custom passes to override the result of NoGhcTc
. Otherwise, it is impossible to have a custom pass that largely shares the instances of GhcPass p
.
For example, while implementing conversion for Match
GhcTc
to With Typed GhcTc
, we get
convertMatch :: Match GhcTc body -> Match CustomPass body'
matchType (Match ext (ctxt :: HsMatchContext (NoGhcTc GhcTc)) ...) = Match ext (ctxt' :: HsMatchContext (NoGhcTc CustomPass)) ...
-- HsMatchContext contains a field `mc_fun :: LIdP p`
-- If we have IdP CustomPass = Var
-- and as NoGhcTc GhcTc = GhcRn, NoGhcTc CustomPass = CustomPass
-- we now need to conjure up a `Var` from `Name`. Clearly this is not ideal.
-- If we instead allow CustomPass to override its NoGhcTc instance, such that
-- NoGhcTc CustomPass = CustomPassRn, we can work around this issue.
-- Thus, we have
type family NoGhcTc (p :: Type) where
-- this way, GHC can figure out that the result is a GhcPass
NoGhcTc (GhcPass pass) = GhcPass (NoGhcTcPass pass)
NoGhcTc other = NoGhcTcNonGhc other
-- | Allows passes other than GhcPass to customize the result of NoGhcTc
type family NoGhcTcNonGhc (p :: Type)
One big question that remains is how to get the type of a HsWrap
expression.
hsExprType' (XExpr (WrapExpr (HsWrap wrap x))) = (error "??? fill this in", XExpr (WrapExpr (HsWrap wrap x')))
where (ty, x') = hsExprType' x
Related tickets: #17331, #15320, #16804, #12706
TODO:
- Can anything be done about
HsTcBracketOut
? - Make
.hie
file generation use this mechanism - Tests