Note [Typechecking data constructors]
As per Note [Polymorphisation of linear fields] in GHC.Core.Multiplicity, linear fields of data constructors get a polymorphic multiplicity when the data constructor is used as a term: Just :: forall {p} a. a %p -> Maybe a So at an occurrence of a data constructor we do the following: 1. Typechecking, in tcInferDataCon. a. Get the original type of the constructor, say K :: forall (r :: RuntimeRep) (a :: TYPE r). a %1 -> T r a Note the %1: it is linear b. We are going to return a ConLikeTc, thus: XExpr (ConLikeTc K [r,a] [Scaled p a]) :: forall (r :: RuntimeRep) (a :: TYPE r). a %p -> T r a where 'p' is a fresh multiplicity unification variable. To get the returned ConLikeTc, we allocate a fresh multiplicity variable for each linear argument, and store the type, scaled by the fresh multiplicity variable in the ConLikeTc; along with the type of the ConLikeTc. This is done by linear_to_poly. If the argument is not linear (perhaps explicitly declared as non-linear by the user), don't bother with this. 2. Desugaring, in dsConLike. a. The (ConLikeTc K [r,a] [Scaled p a]) is desugared to (/\r (a :: TYPE r). \(x %p :: a). K @r @a x) which has the desired type given in the previous bullet. The 'p' is the multiplicity unification variable, which will by now have been unified to something, or defaulted in `GHC.Tc.Zonk.Type.commitFlexi`. So it won't just be an (unbound) variable. So a saturated application (K e), where e::Int will desugar to (/\r (a :: TYPE r). ..etc..) @LiftedRep @Int e and all those lambdas will beta-reduce away in the simple optimiser (see Wrinkle [Representation-polymorphic lambdas] below). But for an /unsaturated/ application, such as `map (K @LiftedRep @Int) xs`, beta reduction will leave (\x %Many :: Int. K x), which is the type `map` expects whereas if we had just plain K, with its linear type, we'd get a type mismatch. That's why we do this funky desugaring. Wrinkles [ConLikeTc arguments] Note that the [TcType] argument to ConLikeTc is strictly redundant; those are the type variables from the dataConUserTyVarBinders of the data constructor. Similarly in the [Scaled TcType] field of ConLikeTc, the types come directly from the data constructor. The only bit that /isn't/ redundant is the fresh multiplicity variables! So an alternative would be to define ConLikeTc like this: | ConLikeTc [TcType] -- Just the multiplicity variables But then the desugarer would need to repeat some of the work done here. So for now at least ConLikeTc records this strictly-redundant info. [Representation-polymorphic lambdas] The lambda expression we produce in (4) can have representation-polymorphic arguments, as indeed in (/\r (a :: TYPE r). \(x %p :: a). K @r @a x), we have a lambda-bound variable x :: (a :: TYPE r). This goes against the representation polymorphism invariants given in Note [Representation polymorphism invariants] in GHC.Core. The trick is that this this lambda will always be instantiated in a way that upholds the invariants. This is achieved as follows: A. Any arguments to such lambda abstractions are guaranteed to have a fixed runtime representation. This is enforced in 'tcApp' by 'matchActualFunTy'. B. If there are fewer arguments than there are bound term variables, we will ensure that the appropriate type arguments are instantiated concretely, such as 'r' in ( /\r (a :: TYPE r). \ (x %p :: a). K @r @a x) @IntRep @Int# :: Int# -> T IntRep Int# See Note [Representation-polymorphic Ids with no binding] in GHC.Tc.Utils.Concrete C. In the output of the desugarer in (4) above, we have a representation polymorphic lambda, which Lint would normally reject. So for that one pass, we switch off Lint's representation-polymorphism checks; see the `lf_check_fixed_rep` flag in `LintFlags`.
References 3
- Polymorphisation of linear fields GHC.Core.Multiplicity
- Representation polymorphism invariants GHC.Core
- Representation-polymorphic Ids with no binding GHC.Tc.Utils.Concrete
Referenced by 11
- GHC.HsToCore.Expr call site ×2
- GHC.Tc.Gen.Head call site ×2
- Polymorphisation of linear fields GHC.Core.Multiplicity
- GHC.Core.SimpleOpt call site
- GHC.Hs.Expr call site
- Eta-expanding rep-poly unlifted newtypes GHC.Tc.Gen.App
- GHC.Tc.Gen.App call site
- GHC.Tc.Gen.Expr call site
- GHC.Tc.Zonk.Type call site