Note [Representation-polymorphic Ids with no binding]
We cannot have representation-polymorphic or levity-polymorphic function arguments. See Note [Representation polymorphism invariants] in GHC.Core. That is checked in 'GHC.Tc.Gen.App.tcInstFun', see the call to 'matchActualFunTy', which performs the representation-polymorphism check. However, some special Ids have representation-polymorphic argument types. These are all GHC built-ins or data constructors. They have no binding; instead they have compulsory unfoldings. Specifically, these Ids are: 1. Some wired-in Ids, such as coerce, oneShot and unsafeCoerce# (which is only partly wired-in), 2. Representation-polymorphic primops, such as raise#. 3. Representation-polymorphic data constructors: unboxed tuples and unboxed sums. 4. Newtype constructors with `UnliftedNewtypes` which have a representation-polymorphic argument. For (1) consider badId :: forall r (a :: TYPE r). a -> a badId = unsafeCoerce# @r @r @a @a The (partly) wired-in function unsafeCoerce# :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep) (a :: TYPE r1) (b :: TYPE r2). a -> b has a convenient but representation-polymorphic type. It has no binding; instead it has a compulsory unfolding, after which we would have badId = /\r /\(a :: TYPE r). \(x::a). ...body of unsafeCorece#... And this is no good because of that rep-poly \(x::a). So we want to reject this. On the other hand goodId :: forall (a :: Type). a -> a goodId = unsafeCoerce# @LiftedRep @LiftedRep @a @a is absolutely fine, because after we inline the unfolding, the \(x::a) is representation-monomorphic. Test cases: T14561, RepPolyWrappedVar2. For primops (2) and unboxed tuples/sums (3), the situation is similar; they are eta-expanded in CorePrep to be saturated, and that eta-expansion must not add a representation-polymorphic lambda. Test cases: T14561b, RepPolyWrappedVar, UnliftedNewtypesCoerceFail. The Note [Representation-polymorphism checking built-ins] explains how we handle cases (1) (2) and (3). For (4), consider a representation-polymorphic newtype with UnliftedNewtypes: type Id :: forall r. TYPE r -> TYPE r newtype Id a where { MkId :: a } bad :: forall r (a :: TYPE r). a -> Id a bad = MkId @r @a -- Want to reject good :: forall (a :: Type). a -> Id a good = MkId @LiftedRep @a -- Want to accept Test cases: T18481, UnliftedNewtypesLevityBinder (4) is handled differently than (1) (2) and (3); see Note [Eta-expanding rep-poly unlifted newtypes].
References 3
- Representation polymorphism invariants GHC.Core
- Eta-expanding rep-poly unlifted newtypes GHC.Tc.Gen.App
- Representation-polymorphism checking built-ins GHC.Tc.Utils.Concrete
Referenced by 3
- GHC.Tc.Gen.App call site
- Typechecking data constructors GHC.Tc.Gen.Head
- Positional information in representation-polymorphism errors GHC.Tc.Types.Origin