Note [Positional information in representation-polymorphism errors]
Consider an invalid instantiation of the 'catch#' primop:
catch#
:: forall {q :: RuntimeRep} {k :: Levity} (a :: TYPE q)
(b :: TYPE (BoxedRep k)).
(State# RealWorld -> (# State# RealWorld, a #))
-> (b -> State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld
-> (# State# RealWorld, a #)
boo :: forall r (a :: TYPE r). ...
boo = catch# @a
The instantiation is invalid because we insist that the quantified RuntimeRep
type variable 'q' be instantiated to a concrete RuntimeRep, as per
Note [Representation-polymorphism checking built-ins] in GHC.Tc.Utils.Concrete.
We report this as the following error message:
The result of the first argument of the primop ‘catch#’ does not have a fixed runtime representation.
Its type is: (a :: TYPE r).
The positional information in this message, namely "The result of the first argument",
is produced by using the 'Position' datatype. In this case:
pos :: Position Neg
pos = Result (Argument Top)
ppr pos = "result of the first argument"
Other examples:
pos2 :: Position Neg
pos2 = Argument (Result (Result Top))
ppr pos2 = "3rd argument"
pos3 :: Position Pos
pos3 = Argument (Result (Argument (Result Top)))
ppr pos3 = "2nd argument of the 2nd argument"
It's useful to keep track at the type-level whether we are in a positive or
negative position in the type, as for primops we can usually tolerate
representation-polymorphism in positive positions, but not in negative ones;
for example
($) :: forall {r} (a :: Type) (b :: TYPE r). (a -> b) -> a -> b
This positional information is (currently) used to report representation-polymorphism
errors in precisely the following two situations:
1. Representation-polymorphic Ids with no binding, as described in
Note [Representation-polymorphic Ids with no binding] in GHC.Tc.Utils.Concrete.
This uses the 'FRRRepPolyId' constructor of 'FixedRuntimeRepContext'.
2. When inserting eta-expansions for deep subsumption.
See Wrinkle [Representation-polymorphism checking during subtyping] in
Note [FunTy vs FunTy case in tc_sub_type_deep] in GHC.Tc.Utils.Unify.
This uses the 'FRRDeepSubsumption' constructor of 'FixedRuntimeRepContext'. References 3
- Representation-polymorphic Ids with no binding GHC.Tc.Utils.Concrete
- Representation-polymorphism checking built-ins GHC.Tc.Utils.Concrete
- FunTy vs FunTy case in tc_sub_type_deep GHC.Tc.Utils.Unify
Referenced by 2
- GHC.Tc.Types.Origin call site ×2