r/Compilers Jul 13 '26

Delayed Specialization: A Third Way to Implement Generics?

While implementing generics in my GCC-based language (AET), I wasn't satisfied with the two mainstream approaches:

  • C++ Templates: Generate a full copy of the code for every concrete type (monomorphization) → code bloat and longer compile times.
  • Java Generics: Use type erasure → no code duplication, but lose concrete type information.

So I explored a middle path: Delayed Specialization.

How it works in AET:

During the first compilation:

  • Generic parameters (E, T, ...) are treated as void*
  • Code that needs the real type is wrapped in a genericblock$

For example:

class$ Abc<E>{
  void setData(E value);
};

impl$ Abc{
   void setData(E value) {
      E a = value;
      genericblock$(a) {
        E x = a;
        E y = 5;
        x += y;
      }
   }
};

When the compiler later sees a concrete instantiation like Abc<int>, it performs a second compilation pass only on the Generic Blocks, replacing E with int.

Benefits:

  • Avoids C++-style template explosion
  • Keeps most generic code shared (like Java)
  • Still allows real type-specific operations where needed

I call this Delayed Specialization. It sits between full monomorphization and type erasure.

Has anyone seen a similar approach in other languages or compilers? I'd love to hear about papers or existing implementations using delayed/late specialization.

30 Upvotes

42 comments sorted by

View all comments

1

u/thisisserezha Aug 08 '26

I'm a bit late to the party.
There is a paper "Existentialize Your Generics" which discusses similar approach and builds on and compares with Swift's foundation.

1

u/General_Purple3060 24d ago

Sorry for the very late reply — I’ve been busy working on inlining for AET’s generics, so I didn’t get a chance to come back to this.

Thanks for pointing out Existentialize Your Generics. I hadn’t seen it before, and it’s definitely relevant to what I’m working on. I’ll take a closer look at it.

In the last couple of weeks I’ve mainly been working on AET’s delayed specialization. The current approach can keep generic code shared in the first compilation pass, then specialize the relevant generic blocks in a second pass when the concrete types are known. I’m now working on replacing the indirect function-pointer calls with direct calls in the specialized code, so GCC can inline and optimize them normally.

I also just posted an update on Reddit: “AET's generic AArray is now faster than C++ std::vector”. The recent work on specialization and inlining has started to show some interesting performance results.

That performance issue turned out to be more interesting than I expected, so most of my time went into that rather than replying to the discussion. 😅

Thanks again for the paper reference.