Carbon Copy No.9: Generics Part I #6397
wolffg
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Carbon Copy, November 2025
Here is the new Carbon Copy, your periodic update on the Carbon language!
Carbon Copy is designed for those people who want a high-level view of what's happening on the project. If you'd like to subscribe, you can join [email protected]. Carbon Copy should arrive roughly (sometimes extremely roughly) every other month.
Toolchain update
Work on the toolchain continues. Here's a recent example of complex interop:
Under the covers this is building a Clang AST from these C++ sources, then pulls what's needed out of the AST into the
Cpppackage in Carbon. Note that the C++ constructorRE2()is overloaded, so Clang is choosing which implementation to call.And finally, since
FullMatchis a variadic template, all of the C++ machinery gets called in the context of Carbon including template argument deduction and instantiation.You can play with a more complete example by running
bazel build -c opt //examples/re2_playgroundin a recent Carbon checkout.Memory safety update
We are developing a memory safety model that allows significantly more incremental migration for existing C++ code without rearchitecture, in particular models that allow mutable aliasing. We first looked at a Rust-like type capability model, with shared mutability inspired by Ante, but our current focus is researching approaches that annotate functions with effects. This has been inspired by recent work; see:
The advantage of this approach is that it appears to allow more flexibility to prove more code pattern-safe, including many code patterns commonly used in C++. However, this comes at the cost of increased complexity when specifying a function's contract. Our current work is collected in our memory safety drive folder, where we are tackling individual topics in a sequence of "safety units."
Spotlight: Generics Part I
In this Carbon Spotlight, we're taking a first look at generics. Carbon takes two major approaches to generics: checked generics, which is the modern idiomatic core approach, and template generics, which are designed mainly for C++ compatibility and migration. Today we'll discuss checked generics.
Checked generics provide three major features:
First, they provide compilation speed. The compiler only needs to check the body of a generic function once, when it is defined. This stands in contrast to C++ templates, which require checks and rechecks during compilation for every instantiation.
Second, they give early and clear errors: Early type checking directly leads to clear errors. Instead of late-binding errors resulting in long, confusing template diagnostics, users receive error messages that plainly show which requirements are not met. We strive to prevent monomorphization errors entirely, although they remain possible in rare edge cases.
Finally, checked generics use nominal constraints: Carbon types satisfy criteria by explicitly declaring what interfaces they implement ("nominally"), rather than (perhaps coincidentally) having functions with specific names and parameters ("structurally").
Let's take a look, then, at how Carbon handles polymorphism through interfaces and checked generic functions.
Carl Linnaeus would be proud
Carbon only supports single inheritance. In an animal class hierarchy, we might have
MammalandInsectbase classes which define features like number of legs. All children ofInsectshould have six legs, while all children ofMammalproduce milk.1However, some subclasses share a characteristic like fur. We want to have predictable behavior for handling hair, but we can't make
HairyAnimala base class ofInsect, because although bees are furry, ants are not2. For checked generics, we want the compiler to be sure brushing a given object is supported before allowing it.So, let's get started.
Classes that implement the
Hairyinterface can beBrushed. Interfaces function as the only static open extension mechanism in Carbon. This means that the capabilities required by a generic function are clearly encapsulated in the interface constraints, making type checking possible without viewing all potential implementations.Let's now define a checked generic function for
Groom, and specialize it for various pets. The[...]covers implicit parameters, which are arguments the caller doesn't explicitly pass in `(`...`)`. (As covered in our last newsletter,selfis a kind of implicit parameter.):!marks a checked compile-time parameter, in contrast to runtime parameters marked with:.If there were a typo here, the error is immediate (in contrast to C++).
We need a class to implement the interface, so let's pick a cat as they are pretty brushable.3
The
implline indicates thatCatisHairy; that is, it will fulfill the promise made byHairywith aBrushimplementation. Iffn Brushweren't defined, that would be a compile error at that location.We can add a bee, too, as bees need to look good, but let's also add a duck that can be brushed, but isn't hairy.
Now let's try it out:
Interfaces like
Hairyprovide static open extension, allowingCatandBeeto define their own implementations of the methods specified by the interface, decoupling the caller (Groom) from the implementations for each type. And, it's a nominal Interface, since duck-typedDuckcan't brush because it doesn't explicitly implement the behavior.See the Compiler Explorer version that runs, and the one that shows errors.
Further with generics
Generics serve as a primary mechanism for achieving many critical architectural functions within Carbon. They replace what other languages would accomplish using multiple inheritance, as shown here, but they are also the core mechanism for overriding operators.
While checked generics are the preferred mechanism for idiomatic Carbon code, we maintain templates for dealing with C++ interoperation and providing a migration path. Templates follow a duck-typing approach, allowing incremental migration to the more rigorous checked generics system.
Coming up soon in Spotlight: More generics! We've barely scratched the surface. If you have questions or specific interests, don't hesitate to follow up with us on Discord.
More to read:
Carbon out and about
Recent proposals and issues
If you want to keep up on Carbon’s proposals and issues, follow "Last Week In Carbon". Check out the RSS feed!
Recently accepted proposals including:
Recently closed leads issues including:
Selfappear in thewhereexpression ofrequire?long,long long) and their operations?Destroyuse a blanket impl forclasstypes, or should it be instantiated per-class?r#Core?Wrap-up
Don't forget to subscribe! You can join [email protected]. If you have comments or would like to contribute to future editions of Carbon Copy, please reach out. And, always, join us any way you can!
Yours in hoping we can we can go on a hike,
Wolff, Josh, Richard, and the Carbon team
Footnotes
Some insects produce "milk", too, but we digress. ↩
But what of the velvet ant? It's a wasp. ↩
But wait! I hear you cry. What of a Sphynx cat? True, they aren't as brushable as, say, a fuzzy Scottish Fold, but Sphynx cats are covered in a downy hair that you could, in fact, brush. Technically correct is the best kind of correct. ↩
Beta Was this translation helpful? Give feedback.
All reactions