Skip to content

Typecheck record update via desugaring in tcExpr

CarrieMY requested to merge wip/T18802 into master

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 Ids 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.

Edited by sheaf

Merge request reports