GC shape stenciling in Go generics

Go’s new code-sharing trick has programmers arguing over speed, size, and compiler drama

TLDR: Go handles reusable code with a compromise: similar data types can share compiled code instead of each getting their own copy. Commenters are split on whether that’s a smart space-saving move or a performance compromise, with Rust and Swift fans rushing in to compare receipts.

Go’s generics story just got the internet comment-section treatment, and honestly? That’s where the real action is. The article explains that when Go writes reusable code, it doesn’t go full “make a brand-new copy for every type” like Rust or C++, and it doesn’t fully squash everything into one vague blob like Java either. Instead, it picks a messy middle path: types that look similar enough to the garbage collector can share the same compiled code. In plain English, Go is trying to save space without giving up too much speed.

The comments quickly turned this into a classic programmer cage match. One camp was basically, “actually, this is pretty decent”. User jchw praised Go for striking a balance, especially compared with Rust, where compile times can feel like a life choice. That sparked the familiar subtext every developer knows: do you want blazing-fast programs, or do you want to finish compiling before retirement?

But the skeptics showed up fast. drivebyhooting came in hot, arguing the biggest problem is that this design can block inlining—one of the compiler’s favorite tricks for making code faster. Translation: some developers fear Go’s compromise could leave performance on the table. Meanwhile, munificent added a classy “other languages did it differently” flex, pointing to Swift’s more elaborate approach. And of course, in true community fashion, someone dropped a self-plug mega-doc for the reverse-engineering nerds. The vibe? Equal parts thoughtful debate, subtle language-war sniping, and “come read my 40-page side quest.”

Key Points

  • The article compares three generic implementation strategies: full monomorphization, type erasure, and Go’s GC shape stenciling.
  • Rust is shown to generate separate concrete function bodies for different type instantiations of a generic function.
  • C++ templates are described as creating specializations for concrete argument sets, with duplicate copies resolved by the linker.
  • Java generics are described as using type erasure, which replaces type parameters with `Object` or a bound and can require casts and boxing.
  • Go’s shipped generics implementation is described as monomorphizing code by GC shape so multiple types with the same shape can share one compiled body.

Hottest takes

"Go's approach to generics is decent. It gets some of the benefits with some of the downsides." — jchw
"The biggest issue with stenciling is lack of inlining." — drivebyhooting
"Swift is able to avoid monomorphizing even when the type arguments have different GC shapes" — munificent
Made with <3 by @siedrix and @shesho from CDMX. Powered by Forge&Hive.