Typecheck record update via desugaring in tcExpr
This patch typechecks record updates by desugaring them inside the typechecker using the HsExpansion mechanism, and then typechecking this desugared result, thus implementing the plan outlined in #18802 (closed).
Example:
data T p q = T1 { x :: Int, y :: Bool, z :: Char }
| T2 { v :: Char }
| T3 { x :: Int }
| T4 { p :: Float, y :: Bool, x :: Int }
| T5
The record update e { x=e1, y=e2 }
desugars as follows
let { x' = e1; y' = e2 } in
case e of
T1 _ _ z -> T1 x' y' z
T4 p _ _ -> T4 p y' x'
The desugared expression is put into an HsExpansion, and we typecheck that.
We use IdSig
to let-bind the Id
s to allow higher-rank types. Example:
data R b = MkR { f :: (forall a. a -> a) -> (Int,b), c :: Int }
foo r = r { f = \ k -> (k 3, k 'x') }
In this situation we essentially need to give a partial type signature
to the let-bound variable for the update at field f
:
ds_foo r =
let f' :: (forall a. a -> a) -> (Int, _b)
f' = \ k -> (k 3, k 'x')
in case r of
MkR _ b -> MkR f' b
This is achieved by using IdSig
as explained in Wrinkle [Using IdSig]
in Note [Record Updates] in GHC.Tc.Gen.Expr
.