WIP: Experiment with a boxing data family
I am attempting to add boxing data constructors that work for all representations. See #21165 (closed), as well as #22336, #20269, #17521.
This hacky and experimental MR defines a wired-in data family
type Box :: forall {r :: RuntimeRep}. TYPE r -> Type
data family Box @r a
together with two wired-in Id
s
box :: forall {r :: RuntimeRep} (a :: TYPE r). a -> Box a
unbox :: forall {r :: RuntimeRep} (a :: TYPE r). Box a -> a
These are defined in GHC.Types
and re-exported in GHC.Exts
.
This data family behaves as if there are instances for each concrete RuntimeRep
Rep
:
data instance Box @Rep b = MkBox[Rep] b
In desugaring (see GHC.HsToCore.Utils.mkCoreAppDs
), we eliminate occurrences of box
/unbox
:
box @{Rep} @ty x
-- turns into -->
MkBox[Rep] @ty x |> sym co
unbox @{Rep} @ty x
-- turns into -->
case (x |> co) of
MkBox[Rep] y -> y
Here, we create a data family instance on the fly, at representation Rep
. The representation TyCon
is R:Box[Rep]
, with a single data constructor MkBox[Rep] :: forall (a :: TYPE Rep). a -> R:Box[Rep]
and coercion co = 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 only Nominal
roles are allowed in data families. This allows coercing between Box a
and Box b
when a
and b
are representationally equal.)
Note that the representation-polymorphism checks ensure that box
always appears applied to an argument with a concrete runtime representation (although this doesn't happen right now, just because of how I'm wiring box
in). This isn't the case for unbox
; fixing that would be a part of #21906 (closed).
For code generation, I hook into GHC.StgToCmm.DataCon
to add constructor info tables on the fly to modules which use box
or unbox
. There's a very hacky IORef
there to make sure I don't define duplicate info tables.
To reiterate: this MR consists of a bunch of hacks piled on top of each other, but I hope it can be a good first step to solving this problem. Test case T21165 demonstrates how this is all working in practice.