Make `wrapBox` work for AddrRep, TupleRep, SumRep, VecRep
!8750 (merged) beefed up our ability to allocate a box for many different representations.
Notable exceptions are AddrRep
, TupleRep
, SumRep
and VecRep
.
#22336 suggests to give up with a good error message when encountering these representations. This ticket is more ambitious: It asks for boxes for all these representations. This would be tremendously helpful for #17521 and #20269.
But since TupleRep
and SumRep
are recursive, there are an inifinite number of different representations to cover. Hence we can never catch all of them with a finite number of *Box
data types as has been begun in ghc-prim:GHC.Types
.
Proposal
-
Define a wired-in type or data family
type Box :: forall {r :: RuntimeRep}. TYPE r -> Type data family Box @r a
Some instances of this family could be defined to delegate to the existing
*Box
data types inghc-prim:GHC.Types
, but the hard problem remains with unboxed tuples. This is the tricky part! We'll discuss the design below.!9353 proposes to create a data family instance on the fly, at representation
Rep
. The representationTyCon
isR:Box[Rep]
, with a single data constructorMkBox[Rep] :: forall (a :: TYPE Rep). a -> R:Box[Rep]
and coercionco = D:R:Box[Rep] <ty>_N :: Box @Rep ty ~R# R:Box[Rep] ty
. (Side note: this data family has roles[Nominal, Representational]
, whereas usually onlyNominal
roles are allowed in data families. This allows coercing betweenBox a
andBox b
whena
andb
are representationally equal.) (Kindly stole this explanation from @sheaf.)I want to add that we already have matching heap objects, if I understand
CONSTR
correctly. Maybe we could also pickCONSTR_STATIC
when applicable. And of course we can optimise toCONSTR_p_n
if we have a fitting combination for the givenr
(which will be 99% of cases). So I think we might not even need to generate an excessive amount of info tables for the specialMkBox
DataCons.Having
Box
would resolve #20269. -
#17521 also wants to offer an API to the user so that unlifted bindings at the top-level are possible (and memoised). One could imagine special, wired-in functions
box :: forall {r :: RuntimeRep} (a :: TYPE r). a -> Box a unbox :: forall {r :: RuntimeRep} (a :: TYPE r). Box a -> a
which basically desugar to something that GHC could resolve with
GHC.Core.wrapBox
. It might be possible to put them in a type classBoxing
, but I don't yet see the added value of doing so.
Note that (1) can be done independently of (2), but I think it makes sense to do them together.
The instances for Box
might re-use many of the existing *Box
types in ghc-prim:GHC.Types
or might not. Not sure. But upon further reflection, I don't think !8750 (merged) brought us any closer to a satisfying resolution of either #20269 or #17521.