![A rat. For reasons. The subtitle is a quote from Bjarne Stroustrup. Suffice to say, he was not thinking of Carbon when he uttered these words. At least since this quote is already thirty (30!!!) years old.](https://herecomesthemoon.net/2025/02/carbon-is-not-a-language/images/dithers/carbon-rat_dithered.png)
A rat. For reasons. The subtitle is a quote from Bjarne Stroustrup. Suffice to say, he was not
thinking of Carbon when he uttered these words. At least since this quote is already thirty
(30!!!) years old.
Toggle original/dithered image
In case you’ve not heard of it, Carbon is Google’s experimental
open-source “C++-successor
language”. As a very rough first approximation, think Objective-C/Swift, Java/Kotlin, C/C++, C++/Carbon.
It is also frequently mentioned in the same breath as Herb Sutter’s Cppfront and Sean Baxter’s Circle (and
Rust, surprise surprise).
Like with any ‘successor language’, the overall goal includes (at the bare minimum) near-seamless
interoperability, as well as significant improvements over the original language.
(Otherwise it can hardly be called a successor, duh.)
If you’ve clicked on the article, you’re probably waiting for me to admit that I’m lying, and to tell you
that (in fact) Carbon is a programming language.
And yes, it’s true! Carbon is a programming language. (Or rather, it’s aspiring to be a
programming language. Carbon is an experimental project and hasn’t hit its 0.1 release milestone yet. The
Carbon developers are very transparent about this.)
But in my humble opinion, thinking of Carbon as a ‘programming language’ is kind of missing the point. Let
me tell you how I think about Carbon, and why I think that it’s more interesting than most people give it
credit for:
Carbon is a concentrated experimental effort to develop tooling that will facilitate automated
large-scale long-term migrations of existing C++ code to a modern, well-annotated programming language
with a modern, transparent process of evolution and governance model.
The entirety of Carbon (the language, as well as the project) is built around making this goal possible.
(Disclaimer, I don’t speak for Carbon, take my words with a grain of salt.)
Why?
In this post, I want to convince you of the following points:
-
Carbon is a project to investigate the possibility of a large-scale reduction of C++ technical debt via
automated code migration. -
Many so-called ‘successor languages’ are nothing like this. They don’t make
automated code migration an explicit goal, and generally build a layer of abstraction on top of
or rely on their host language. -
All of this is downstream of Google’s disagreements with the C++ Standard Committee. In fact, while all
of this is about reducing technical debt, it’s also about reducing the organizational costs involved in
having to coordinate migrations and language evolution with the committee. - Developing a new programming language is probably necessary to achieve the goals of the project.
I’d like to bring special attention to the point about governance: This isn’t just a technical issue. It’s
a governance issue. It’s a “We just straight-up disagree on the future direction of the C++ programming
language.” sort of issue. I already went over these cultural disagreements in
a previous post.
(The astute reader will note that you can evolve and govern your own programming language however you
want, without needing to deal with WG21 (aka the C++ Standard Committee, aka the authority that decides
what C++ is.))
At this point I’d love to reach for the Herb Sutter “We must minimize the need to change existing
code.” quote again,
but I’ll instead just state the obvious:
A large-scale migration to a different programming language is the opposite paradigm. As far as
changes to existing code go, it’s uncompromising. It’s an approach that’s only going to work for a subset
of people, and in fact,
Carbon’s goal document
lists “We consider it a non-goal to support legacy code for which the source code is no longer available”.
In other words, the language is not for everyone. That’s fine! I am still very interested in it. I care
about Carbon since I believe that it’s trying to solve the hardest problem C++ is currently facing.
This isn’t any single technical issue (there are many, many of those), no, and it’s not even a
broad concern such as memory safety.
It’s the problem of C++ slowly calcifying and struggling to modernize. It’s about ABI, about dozens of
tools but no agreed upon standards, and it’s about backwards compatibility. It’s about allowing existing
C++ code to evolve, modernize and change, in spite of decades of technical debt, multiple
implementations, and many different users with different expectations and requirements.
This is, in other words, an incredibly hard problem, and a long-term project.
If you believe that certain multi-million line C++ codebases are still going to exist in twenty years,
then you should understand the business case for Carbon.
A short lesson in history
Let’s briefly summarize the backstory for those who haven’t kept track. You could (very roughly) say that
Google is developing Carbon due to conflicts with WG21, and disagreements about the future of the C++
language.
What matters is that Google contributed to WG21 for many years, and that it has a vested interest in the
future of the language, due to owning many, many million lines of C++ code. It’s hard to
overstate how critical C++ is for Google’s infrastructure, and for modern technology in general.
The short summary is that Google’s developers (not just Google’s, mind you) disagreed with other parts of
the committee about the
future direction of the C++ language. There are a lot of reasons for this, and
a lot of ink has been spilled on the
topic. Eventually, after trying to work with WG21 for many years, Google basically threw in the towel.
(You cannot blame them. They tried hard, and the WG21 process is notoriously slow and frustrating.)
At this point, a lot of people might think that the core disagreement between Google and WG21 was about
‘memory safety’, or something like that.
It wasn’t!
The current memory safety hype is a pretty big deal for C++, but the ball was already rolling several
years ago. All of this started with concerns about C++’s complexity
and performance.
It turns out that fixing certain issues would require backwards incompatible changes (bad!). Coordinating
this across the entire C++ ecosystem would be more or less impossible.
I’ll not get into the details and instead point at Chandler Carruth’s
‘There are no zero-cost abstractions’
for an example: It pins down how first of all, std::unique_ptr
has a runtime overhead, and
second of all, how fixing this would require an ABI-break and a language change.
(That doesn’t mean Google doesn’t care about memory safety, of course. They do. But memory safety isn’t
what started the whole conflict, even though it’s currently carrying the torch. That’s why memory safety
is still relevant to all of this, especially since making C++ memory safe without compromising the vision
of the standard committee looks more or less impossible.)
Migration & Language Evolution
First of all, that Carbon has automated code migration as one of its goals should be clear. The
Carbon people are
very explicit about this. It’s also a common theme in
their talks.
This is, first and foremost, about moving away from the “We mustn’t break existing code, so we
had to squeeze in this new feature/syntax in some awkward way somehow.” approach to language
evolution. (co_await
and the (proposed) reflection operator (^^
) are sending
their regards.)
This approach to language evolution kind of sucks. It’s not like the committee doesn’t
understand the problem, or doesn’t want to evolve the language. The committee is not
evil, and it’s not your enemy. C++ is just incredibly hard to evolve for all sorts of reasons, which would
honestly justify an article on their own (ABI, multiple implementations and the committee process, no
unified ecosystem, no editions or epochs system, no unified migration tooling, widespread dynamic linking,
etc.)
Carbon’s goal is to move away from that.
How? Via automated tooling, a well-defined process of language evolution with clear guarantees, etc.
Carbon is still highly experimental, so the details are still WIP. If I had to guess, I’d say they’re
planning to follow in the footsteps of other modern languages. As an example, consider how Rust manages:
-
Have a new ’edition’ every three years or so. Each edition is allowed to make certain breaking changes,
but modules from separate editions can be compiled and linked together. -
Ship automated migration tooling with the language, which allows an automatic migration of code to the
new edition whenever possible. -
If you want to eg. introduce a new keyword, you reserve it one edition ahead of time.
Raw Identifier syntax
allows migration and use of old code that still uses this keyword as an identifier.
In contrast to this, I don’t think there’s any feasible roadmap to get C++ to this state.
It’s only possible with an ecosystem split, and that’s exactly the point.
Let me reiterate this. If there’s one thing you take from this article, it’s this here: The
point of Carbon is to make it possible to take existing C++ code and to put it onto a path
towards a modern, well-defined process for future evolution and changes.
This is the point. If you want to be cynical, it’s about cutting the dependency on the standard committee,
and it’s about allowing any forwards-looking, backwards-incompatible changes at all, without
having to worry about someone else’s ancient binaries from the 80s.
C, C++, Cpp2
I just want to make clear that I believe that Carbon is radically different from
Cpp2 (ie. Herb Sutter’s experimental
project to evolve C++).
The major difference is that Cpp2 tries to leverage the existing C++ language to its full extent, while
Carbon tries to minimize its dependency on C++ wherever possible.
Cpp2 takes the same approach C++ originally did: It transpiles its own code to the host language, and is
thus deeply and intrinsically linked to it. It reuses the C++ standard library with all of its problems,
it aims to maintain the C++ ecosystem instead of splitting it.
Perhaps most importantly, Cpp2 also cannot go lower than C++: It cannot directly interface with
the compiler, since it’s written to be used by “any standard-compliant C++20 compiler”.
It should be obvious that it’s basically impossible for Cpp2 to make meaningful reductions to C++’s
technical debt. Yes, it can be “C++, except with better defaults and syntax.”, but that’s all it can
feasibly be as long as full backwards compatibility is an explicit goal. Reducing C++’s technical debt on
a deeper level is completely out of scope for Cpp2.
It can reduce the number of ways there are to initialize objects by simplifying syntax. It
cannot make any changes that would require an ABI-break, it cannot add null-safety to the
language (eg. unique_ptr
can still be null, variant
can still be valueless), and
it can’t prevent your code from blowing up in exciting ways due to lifetime issues.
Carbon has the advantage that it can make these changes. (eg. Carbon is planning to move away
from exceptions, in favor of treating errors as values.)
Just to be clear, this is fine! I am not saying Cpp2 is bad, and I’m curious to see how the project
develops. I am just highlighting that Carbon and Cpp2 are completely different projects with
completely different scopes and goals.
It is written by Herb Sutter, someone who very clearly loves C++ as it is, and who wants to make
it easier to use. It’s about having a new syntax, and making it trivial to apply best practices
to your C++ code.
This is a great idea, and a much less invasive proposal than Carbon. Carbon isn’t that. Carbon is about
reworking the language from the ground up. It’s about building a new language that can
support almost all of the same semantics, but is still critically different. It’s about reworking the
fundamentals, and building stronger abstractions.
So in short, Cpp2 works with C++, and Carbon is trying to recreate a better C++ from
scratch, while cutting its dependency on C++ almost completely.
Technical feasibility
Is Carbon feasible? I’ll be honest, I have no clue. C++ code is really complicated and this project is
(more or less) unprecedented. (Which is, again, why I am interested in it.)
The reasons why I believe it might be technically feasible at all are simple:
-
Carbon doesn’t attempt to do the impossible: The goal is a tool-assisted migration of idiomatic code,
not a fully automated migration of all code. (What does ‘idiomatic’ mean? Who knows. Probably
something like ‘well-annotated and easy to handle for static analyzers’. Figuring out how to draw the
boundary of which code can be migrated is part of the project.) -
Carbon is capable of leveraging its underlying tooling to do a lot of the hard work. For
example, resolving C++ templates and function calls is handled by Clang and LLVM. This should not be
much of a surprise. Clang can be used as a library, and this is exactly what you’d expect it to excel
at. (Swift is
already doing this for its C++ interop.) -
Carbon already demonstrated that its chosen abstractions are capable of supporting some pretty “fun” C++
features.
Let me quickly substantiate some of that.
Testing
So, here’s the thing. Carbon can
convert your C++ to Carbon and then run it against the old test suite. (Or that’s the plan, at
least.)
(You do have a test suite, right?)
If the code compiles and all tests pass, this should give you confidence in the resulting code
proportional to your confidence in your own test suite. (This is especially helpful for changes
past the initial automated migration, even if it’s just clean-up work.)
This approach is really nice for all sorts of reasons.
First of all, it means that Carbon can leverage
existing C++ test suites to test its own migration and interop capabilities. This is great.
Second of all, it puts some burden on the user and sets a minimal bar for what Carbon means with
‘migration of idiomatic C++’: You should probably have some tests in your code. If you critically
depend on something, then you should have a test for it.
Generalization and unification of C++ features
So.
Member access operators. This example is shamelessly lifted from
‘How Designing Carbon C++ Interop Taught me About C++ Variadics & Bound Members’:
#include
class Foo {
public: std::string a;
};
int main() {
std::string Foo::* pm = &Foo::a; // defines a "pointer" to the member of Foo
Foo foo{}; // define foo of type Foo
std::string _ = foo.*pm; // access field a of foo
}
If you have no idea what you’re looking at: This is legal C++. Calling pm
a ‘pointer’ is a
stretch, in practice it is just an offset relative to the location of an object of this class in
memory.
Two funfacts: First, this can also be used to refer to methods. Second, this value can be null, and it’s
null-value is -1
, since 0
would point to an actual field.
Fun, isn’t it?
When I see a feature like this, my first question would be whether Carbon is even capable of
modeling this specific type of behavior, and it turns out that, yes, they have thought about
this.
Carbon is building literally everything on top of interfaces
(which can broadly be
understood as C++0x Concepts or Rust traits).
There’s a simple reason for that: Carbon wants to support definition-site checked generics
(roughly, you’ll know that a generic function can be instantiated without having to look into the body of
the function. This is not the case for templates.) As a consequence, every possible thing which
you can “do” with a value needs to be implemented as an interface, so that you can specify that an
incoming value fulfills this constraint.
Consequently, member access pointers are implemented via a so-called
BindToValue
interface, which (as far as I can tell) generalizes expressions of the form
x.y
, whether y
is a field, a static member function, a method, a member access
pointer, or who knows what else. Any y
which implements BindToValue(X)
(where
X
is the class of x
) can be used as x.y
.
The pattern of unifying abstractions as interfaces gets used a lot: It turns out that deep within Carbon,
function calls are implemented as a synthesized type which implements some Call
interface.
This is used to unify functions, methods, lambdas, etc. Every single thing in Carbon which you can “call”
is just some value implementing the Call
interface.
Sorry, I’m basically just rehashing parts of Chandler Carruth’s (highly technical) talk here. For the full
picture, please just go and watch it. He’s a great speaker, and I don’t trust myself to get every
technical detail right.
The point is, if you’re wondering what the Carbon people are working on, then it’s this kind of stuff.
They’re building foundations which are general enough to to make all sorts of gnarly C++
semantics (eg. member access pointers) work, but have a much simpler underlying model. (eg. it
unifies everything that can be called, and gives you the ‘concept’/interface for free).
Is this going to work for the rest of the language? Who knows! C++ is complicated, probably too
complicated to manage. That’s the whole reason why Carbon even exists.
Digression: Why not Rust™? Why not C++?
Rust is really just too different for an automated conversion of C++ code to Rust code to be feasible,
it’s as simple as that. I even
wrote an article
getting into the differences in type inference alone.
You have no class inheritance, no templates, no specialization, no ad-hoc function overloads, no implicit
conversions, and there’s still the whole deal with the borrow checker. Any conversion of modern
general-purpose C++ code to Rust basically amounts to a rewrite, which is just not something you can do
with classic automation tooling.
Carbon has the luxury of being able to support both templates and checked generics (ie. something
like Rust traits or C++0x concepts), and a way to migrate between them.
As for a C++-to-more-modern-C++-migration, it just doesn’t solve the question of language evolution.
You’re still heavily limited by what you can do, unless you also commit to a proper fork of C++ and
possibly Clang.
Which…might be viable, but makes it much harder to implement clean abstractions from the get-go. It also
doesn’t help that a fork runs a pretty severe risk of being ‘usable’ right from the get-go (meaning that
people will want to use it, and the boundary between C++ and Carbon will be muddier).
Governance
As I said, Carbon is a moonshot project to allow modern C++ codebases to evolve. (They might stop being
called “C++” in the process, but that’s probably fine. The only constant in life is change, or something
like that.)
The north star goal is, of course, that of a gradual but mostly automated migration of existing C++ code
to Carbon code, followed by additional migrations to fix and improve this code using Carbon’s
modern, more powerful semantics (eg. null safety).
From this angle, and with the historical background in mind, let’s address the elephant in the room
and take a stab at describing how some people feel about Carbon, by rephrasing my interpretation of its
goals in the most cynical way possible. I’m deeply sorry to anyone who’s working on Carbon, since this is
going to feel like I’m twisting a proverbial knife:
Carbon’s primary goal is a large-scale migration of Google’s enormous pile of (highly specific,
exception-less, Abseil and Protobuf-using, Clang-based, Bazel-built) C++ technical debt into a modern
language capable of supporting Google’s needs, and
over whose governance Google is capable of exerting a significant amount of control.
There we go. Do
you see the elephant yet?
It’s pretty hard to miss since I highlighted it. (Sorry, I know that it’s the second time I made that
joke.)
This about the least charitable way to phrase it, of course. I’m bringing this up for the obvious reasons:
Carbon is spearheaded by a big tech company, and people have various concerns.
These include the concern that Google trying to ’take control’ of C++ via a divide-and-conquer approach,
that Carbon will favor Google’s style of C++ at the expense of others, and the classic sentiment that
Carbon will eventually be abandoned and dropped (potentially leaving early adopters out in the dry).
As I already gestured at before, all of this is about trust, and by extension about governance.
As long as we’re willing to say that Carbon is is about reducing the reliance on the C++ Standard
Committee, it’s pretty clear that that governance-shaped hole has to be filled somehow, and that
someone (or some group of people) has to decide the future direction of the language.
I’ll be honest, I can make no guarantees here. I am not working on Carbon, and the dynamics here are far beyond my scope.
I can point out that Carbon is an Apache-licensed open source project,
open for contributors right now, and that it has an explicit “The intent is that […] Carbon remains a community-driven project, avoiding
situations where any single organization controls Carbon’s direction.”
disclaimer
in its FAQ, but that’s not going to convince you if you’re worried about bad intentions.
So. What I can tell you is that I believe that putting governance of the language into the hands
of the open-source community is critical for Carbon’s long-term success, and that Carbon’s developers
understand this.
Whether Carbon will find widespread adoption depends on whether established corporations trust
Carbon’s stewards to handle the language with enough responsibility that migrating their own C++ code to
Carbon seems like a safe offer.
This sort of trust is hard to establish as long as there’s a single owner, especially if that
owner is Google.
Second, That Carbon finds any public adoption at all is also pretty important even if the primary
goal was just to use it purely within Google. This might come as a surprise, but it’s pretty simple:
People who’re expected to use Carbon first need to learn Carbon. This is significantly easier
when Google can rely on a broad ecosystem of tutorials, libraries and discussion boards outside of its
intranet.
So in other words, for Carbon to become successful, it’s critical that there’s a public community, and
that enterprise users of C++ trust Carbon.
These are huge incentives to push the language towards independent community ownership.
Both of these points (trust by enterprise users and need for a public community) were
much less important for Go (which was also
spearheaded by Google), primarily due to Go’s simplicity, the fact that there was far less competition in
the programming language space when Go released, and the fact that it was a language for greenfield
projects. (That is, it didn’t require convincing ancient C++ coders to perform a massive migration and
rework their tool chain.)
My understanding is that
Carbon’s leads understand all of this, and want the project to be community driven. For now, that’s more than good enough for me. For a
project this early in its life-cycle, it’s nice to see that they’re thinking about this at all, and have
made an explicit commitment to community ownership.
Conclusion: There is no free lunch.
The prospect of building a successor to C++–the arguably single most important programming
language currently in existence–sounds like it should be doomed to fail.
I’ll repeat what I said before, and what should be common knowledge: C++ is an incredibly complex
programming language. It’s under-annotated, has multiple implementations (governed by a 2000+ page ISO
Standard document), carries four decades of technical baggage, is full of undefined behavior, and has a
frequently abused turing complete quasi-code-generation meta-programming language built into it.
All of that should make it near impossible to succeed C++. Complexity is in fact a form of job security.
So why am I still relatively confident in Carbon’s potential?
Simple, it’s mainly since the priorities look correct to me. Carbon understands that
-
C++’s inability to evolve, modernize, deprecate, migrate and standardize is the critical issue
which the language is facing today. -
You cannot improve on this without making concessions. This goes both ways: There is old C++ code which
you will not be able to support. At the same time, there are C++ features which you have to
support, whether you want to or not. -
This is a herculean task that requires a massive initial investment (a whole new programming language),
and a complete rethinking of tooling, communication, software engineering and language development
practices.
The inability to evolve is an issue for people who’re just starting to learn C++, and who stumble into
every single footgun that hasn’t been taken care of over the past thirty years.
It’s an issue for people who care for high-quality code, readability or memory safety, and see no viable
path towards getting their C++ codebase into that state.
It’s an issue for committee and compiler contributors, who need to carefully consider how a new
feature will interact with literally everything else the language already supports.
You might disagree with that assessment. It might not be an issue for you personally. That’s
fine. C++ (for a given version, anyway) will stay exactly as it is. It’s not going to go away anytime
soon, and that’s a good thing. People depend on that. Critical infrastructure depends on that.
As for myself, I am incredibly glad to see that someone is trying to take this bull by the horns,
and willing to face this charging billion lines-of-code mountain of complexity and technical debt head-on.
At last but not at least just since it would be really freaking cool if we (humanity, as a whole)
could actually pull it off, and don’t need to pass tales warning people about the dangers of using
std::vector
across the generations.
It might take a while, but that’s fine. This is a long-term project. It has to be a long-term
project to make this work. Once you start thinking about it from that perspective, everything makes a lot
more sense.
Remember, those millions of lines of C++ code are not going to go away anytime soon. They’ll still be
there in a few decades. It’s either a large-scale migration (in some form or another), or nothing.
In the meantime, if you’re remotely interested, I’ll reiterate that I highly recommend Carbon’s talks, eg.
this one.
Addendum
Writing this took significantly longer than expected. The total number of footnotes written and deleted is
about fourty.
Let me know if you got something out of it–It means a lot to me.
Questions, suggestions, comments, writing advice, reading recommendations, music suggestions, pictures of
pets and basically anything else you can think of are all welcome via my contact e-mail at the bottom of
the page.