Skip to content

WIP: Virtual data constructors

Andreas Klebinger requested to merge wip/andreask/virtualCon into master

Seems to mostly work now and we don't allocate virtual constructors but doesn't quite produce optimal code yet.

@monoidal @sgraf812

This MR allows us to safely solve the problem described in #21617 as well as optimizing certain code. The gist of it is this:

For a data type with a single constructor and a singular strict field (either banged or unlifted) where the runtime representation of the field is compatible with lifted-boxed-rep we can omit allocating the constructor at runtime and instead pass around the pointer of the field itself to represent the value. This MR calls the constructor of such a type a virtual constructor as it never actually exists at runtime.

From the original ticket #21617 if we have:

type U :: UnliftedType
data U = U1 | U2 <params> | ...

data L = L U

We never need to allocate the constructor L. Why not?

  • If we have x = L u we just return a pointer to u instead of allocating the constructor.
  • If we have case x of L u -> u when generating code to bind the variable u instead of indexing into the closure for x we simply return the result of evaluating x.

We can apply this to a few more variations of data types as a nice side effect.

Here are a few example types where we can treat their constructor as a virtual constructor:

-- Single strict lifted polymorphic field.
data Indirection a = Ind !a

-- Functions in strict fields.
data IndFun a b = IndFun { unIndFun :: !(a -> b) }

data IndLBool = IndB { unIndB :: !Bool }

data IndIIFunc = IndIIFunc { unFunii :: !(Int -> Int) }

-- Unlifted fields where the type is known.
data LUBool = LB { unBool :: UBool }

Where this, perhaps surprisingly, doesn't work is this type:

data UIndirection (a :: UnliftedType) = UInd { u_unInd :: a }

That's because it could be instantiated with a ByteArray# or similar type which has no entry code.

So code like this:

let x = UInd arr
in seq x ()

would blow up as after the optimization we would try to seq the arr value.

Edited by Andreas Klebinger

Merge request reports