![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)
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.1 (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.2
- 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++ is3.))
At this point I’d love to reach for the Herb Sutter “We must minimize the need to change existing code.” quote4 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 complexity5 and performance.6 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.7)
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.8
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 complicated9 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 <string>
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 room10 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.11 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 is 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 hanging 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 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 Carbon12, 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++—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.13
- 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<bool>
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 forty.
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.