
Carbon is a programming language developed by Google as a successor to C++, and it aims to provide modern safety features while maintaining high performance. It’s designed to offer seamless interoperability with C++ while addressing shortcomings of C++...
Loading summary
Chandler Carruth
Carbon is a programming language developed by Google as a successor to C, and it aims to provide modern safety features while maintaining high performance. It's designed to offer seamless interoperability with C while addressing shortcomings of C such as slow compilation times and lack of memory safety. Carbon also introduces features like a more readable syntax, improved generics, and automatic memory management while still allowing low level control. Chandler Carruth is the creator of Carbon and he leads the C, C, Lang and LLVM teams at Google and he also worked on several pieces of Google's distributed build system. In this episode he joins Kevin Ball to talk about Carbon and the future of the language. Kevin Ball, or K Ball, is the Vice President of Engineering at Mento and an independent coach for engineers and engineering leaders. He co founded and served as CTO for two companies, founded the San Diego JavaScript Meetup, and organizes the AI in Discussion group through latent space. Check out the show notes to follow K. Ball on Twitter or LinkedIn or visit his website K Ball LLC.
Kevin Ball
Chandler, welcome to the show.
Chandler Carruth
Really happy to be here. Really happy to be here.
Kevin Ball
Yeah, I'm excited to dig in. So let's maybe start with a little bit about you, your background, and a little bit about what Carbon is and what led to it.
Chandler Carruth
Sure, sure. I mean, I've been a software engineer at Google for a long time now and when I started I was pretty fresh out of university and didn't really know what I was doing. Kind of got thrown into a bit of the deep end and I was working on a C project with a bunch of amazing folks who are largely teaching me how to be a good software engineer. And I was incredibly frustrated because the C project was just holding me back every single step of the way. Working on the C code base was painful. The the tools were bad, the experience was bad and it seemed like it really, it just, it became an overwhelming kind of problem that we needed to solve and that kind of kickstarted me diving a whole lot deeper into first compilers because I thought maybe the compiler was the problem. And as we got better and better compilers then into the programming language, joined the standards committee, really tried to figure out ways we could much more radically improve C, the experience for all the developers and also the quality of the actual software we're able to put out, at a certain point we weren't actually able to achieve the kind of improvements we needed to. We kept seeing really fundamental risks facing C, really fundamental problems that needed pretty radical changes to the programming language as a whole and kind of how the programming language worked in order to credibly address them today. I think the obvious and really great crystallization of this is around memory safety and the questions around whether we can use memory unsafe programming languages going forward. But that's just the best example of the fundamental problem that we need to make radical changes to really address programmer needs. And the committee and the standardization process and the C language were not realistically going to be able to make the kinds of changes we thought were needed here to address that. And that's where we started working on Carbon. And the flip side of this is we have just. I work at Google and we have an incredibly large C code base, right? We have hundreds and hundreds of millions of lines of C code we've written. We depend on hundreds of millions of lines of C code that the rest of the industry has written in the open source community. And we can't throw that out like that's not going away. We don't have the luxury of rewriting all of that. We don't have the time or the teams to do that. And so we needed something, we could actually bring all of that code along with us, but get the kind of radical transformative change we're hoping for here. And that's kind of how Carbon started off. And really what keeps me really excited about it is to see if we can make those transformative changes to the programming languages will bring the C code and existing software along with us.
Kevin Ball
Yeah, let's talk a little bit about what that means to bring it along. Because when I was looking at the website for Carbon, there was a great line which said existing modern languages already provide an excellent developer experience. Go Swift, Kotlin, Rust and many more developers that can use one of those existing languages should. Now, what in this big legacy C code base keeps you from using one of these languages and connecting it through message passing or something similar?
Chandler Carruth
I mean, sometimes we do. And that's awesome. I mean, Google has almost as much Java code as it does C code and that's great. When we can use it, we have tons of go code getting written. We're increasingly writing Rust code. When you can do that, when you can just have message passing or some kind of nice API boundary, some abstraction boundary between the C software you depend on and new code, that's fantastic. And using one of these languages is amazing. But these abstraction boundaries tend to need to be pretty robust abstraction boundaries. Message passing you mentioned is a great example of one. We actually have a lot of projects to try and get finer grained abstraction Boundaries, lower cost abstraction boundaries. But it's hard. And so the question is, what about all of the code we need to write that doesn't have that abstraction boundary, that is immersed in an incredibly complicated, often tangled mess of C code with no abstraction boundary in sight, or we still want that code to move as well, and that's the code that's kind of getting left behind.
Kevin Ball
Yeah. So this reminds me a lot of TypeScript in some ways, of TypeScript being something that you can take an existing, extremely messy JavaScript code base and start just file by file as you're adding new things or you're touching something, upgrading, and then once you compile it, the program doesn't know, it's just fine.
Chandler Carruth
Yeah, absolutely. And I think typescript's a great thing to think about because there are also different approaches you can take here. TypeScript takes a really important approach. It basically is a superset. If you have valid JavaScript code, it's basically valid TypeScript code as well. This is super valuable for TypeScript and for languages historically like C, did this with C, C to a certain extent, did this with B before it, and bcpl like this is a very, very valuable approach, but it has some limitations. You can't make as radical of changes with that approach. And for a long time this was still the only real approach we had. But I think with languages like Swift and Kotlin, we're seeing a different kind of way to do this, where instead of being just a strict superset, you actually have some deep and fine grained interoperability. But the new code gets to be written entirely in this kind of fairly new clean space that really relies on very advanced compiler technology that's kind of come around in the last few decades. And so that's why you see this in Kotlin for Java and Swift for Objective C. But why not TypeScript? And I think this is kind of confusing to a lot of people. It seems like if this is such a better path, why wouldn't TypeScript use it? I think the thing you have to realize is that so much of the JavaScript in the world wasn't compiled. Even though we have that compiler technology. If you haven't been compiling your JavaScript code, you don't have it available. And so they needed to reach back to the superset model. One of the interesting things we're doing with Carbon is leveraging the fact that we do have compilers for all the C code. We have a rich build system there. We can take this kind of more advanced approach which it opens up more freedom, it gives us more opportunities.
Kevin Ball
So let's maybe dive in a little bit deeper on what that looks like. I think the one that I'm slightly more familiar with is the Java Kotlin example. But there you have the JVM and you have Java bytecode as a sort of target. And so long as you can compile down to that intermediate language now you've got an easy form of interoperability. What does that look like in you mentioned, I think Swift and also in the Carbon world.
Chandler Carruth
This is a great question and I don't know that I know enough about Swift. I'm not a Swift expert. I don't want to speak for that community.
Kevin Ball
We could just go in Carbon too. What does this look like for Carbon?
Chandler Carruth
Yeah, in Carbon we can really dive in there. So superficially it seems like we have something similar because we have llvm and LLVM is kind of this very nice base layer that all these languages sit on top of. And so if we compile down to llvm, you can things seem happy. The interesting problem with that is that LLVM is way too low level. The JVM actually exposes the vast majority of Java semantics. If you can get to the jvm, you can actually interoperate pretty well with Java. But LLVM doesn't expose any C semantics. I don't know if you've looked at like the llvm, like the intermediate representation of LLVM for some C code. It looks nothing like the C code. It's gone.
Kevin Ball
Right?
Chandler Carruth
And so we need something other than that. And that is actually a real challenge. I think we couldn't have done this without the technology that we got in Clang, which is a complete like production quality C compiler, right? We use it for basically all C code across the entire company of Google, all the platforms, they all use Clang. And this compiler gives us not an intermediate representation or a bytecode like the JVM bytecode or LLVM's IR, but it gives us some way of understanding every aspect of the C code. Basically it's the C AST that Clang builds. We can't lower into that though, it's too specific to C, but we can use that to build bridges. And so what we do is on the Carbon side, we're going to basically look at the C ast, figure out how that should kind of manifest inside of Carbon, right? Synthesize anything we need in order to kind of realize that interaction with C in the Carbon side and then Use a combination of both Carbon and Clang, that both of these compilers kind of lower that into LLVM IR to actually implement that interaction. So he's clang to get the fidelity, to get the language semantics, the nuances, the details, and then we lower into the common layer of LLVM for kind of execution and behavior.
Kevin Ball
So when you're compiling Carbon, is that also targeting an ast and it's a different type of thing or like, oh.
Chandler Carruth
This is a great question. It's also a super deep topic because it isn't. So we have a pretty novel architecture for the compiler in Carbon. It looks completely different from anything in Clang, from anything in, like your textbook compiler. I'm only aware of, like, one other modern compiler that's even going in the same direction. We actually both ended up going this direction in parallel. It's the Zig compiler. So we don't have an AST at all. We have your traditional Lexer that produces a stream of tokens. We have a parser that doesn't have any semantic information at all. It doesn't even know what the language constructs are. It's just basically the grammar productions. And it turns the token stream into a very naive parse tree. But we don't ever build a semantic AST the way you would expect from a programming language. From that very syntactical and structural parse tree, we generate what we call a semantic ir. It's kind of like an LLVM iron, but also the opposite, where LLVM IR basically throws away all of the semantics other than the execution model and lowers it as far as it can, as quickly as it can. We keep everything, and so it represents every nuance of semantics, exactly how all of them work. Everything you would expect in an AST is actually in the semantic IR, but it's represented as kind of an executable IR. It's something you could evaluate or lower into LLVM's IR. And this is a really fun model. It makes it really easy to lower into LLVM ir. It's now a much more direct lowering step. It also makes it really easy to do stuff like compile time evaluation and compile time evaluation and metaprogramming have ended up becoming absolutely pervasive in modern programming languages. And so having this representation that tailors itself to those needs gives us a ton of advantages. It also is a lot easier to design this in a way that's fast on modern CPUs. And so one of the big goals of all of Carbon is to have just the fastest compile times that are conceivable across the board.
Kevin Ball
So then, putting this together, if I understand if you're wanting to integrate something carbon and C, what you're going to do is you're going to use Clang to compile the C down to AST level, and you're going to take that AST over, pass it off in some way to the Carbon compiler, where it will translate it to the carbon IR in a way that can interface. You then also compile your carbon down to the carbon ir. That's the layer at which they're going. And then you lower that into llvm.
Chandler Carruth
Yes. And it's more complicated, though.
Kevin Ball
Okay, keep going.
Chandler Carruth
You do all of that, but you also, in parallel, have to build synthetic ASTs in Clang to represent.
Kevin Ball
To represent the carbon.
Chandler Carruth
Carbon constructs.
Kevin Ball
Yeah. So it's bidirectional, essentially.
Chandler Carruth
Bidirectional. You have basically like two compilers going through. And on the carbon side, it's all on the semantic ir and the Clang side, it's all this ast, and they're each kind of telling the other, I need this construct or I need that construct. These are basically like very. They're veneers, right. They always kind of dispatch back into the actual implementation on the other side. But this builds this bidirectional communication. And then we kind of. Both of these compilers then emit a bunch of llvmir, which we merge together and we get the output right. And this lets us have almost arbitrary carbon semantics exposed in C, also arbitrary C semantics in Carbon. And even better, it lets you bounce back and forth between them, because you can't stay on one side of this. If you have a carbon type, you want to pass it to a C API. That API is going to instantiate a C template on that carbon type, and that template's then going to call carbon methods. But those aren't just normal methods, they're going to be generic methods that it needs to pass C types to. And that's going to go back into the carbon side to figure out how that generic treats that C type. And it's going to discover a callback from C in that type that it has to call back into the car. Like it goes back and back and forth.
Kevin Ball
Is there any performance cost when you cross that boundary?
Chandler Carruth
I mean, there has to be some. This is a real abstraction that we're keeping, and this is actually a thing we want to do. We want to have an abstraction between carbon and C, between carbon and Clang we want that abstraction to be fairly rigid so that we can manage the technical debt that we inherit from C, because we are worried about that. But we don't want it to be a small abstraction, we don't want it to be an expensive abstraction. And so we're trying to make it as inexpensive as possible. We're doing everything we can architecturally to let that abstraction be as near zero cost as it can be. But it can't be free.
Kevin Ball
When you're passing data across these layers, are you able to do it in a zero copy way and just pass the pointers around, or do you have to do copies to get it into the new domain?
Chandler Carruth
No copies, it has to be zero copy. So we have basically the same memory model for all of the interrupt. We have to be able to realize kind of the identical ABI and memory layout on each side. So C types, even when we use them in Carbon, they have to be laid out according to the C rules. Carbon types, even when C is using them, have to be laid out according to the Carbon rules. And this really does dive into like why this is such a tight coupling, even though we try to maintain this abstraction like the coupling isn't loose.
Kevin Ball
Right.
Chandler Carruth
It's a deep, deep impact. And this also means we have some constraints. We don't expect to be able to make perfectly exposed Carbon types to C code that we don't compile because we need to tell the compiler how to do fancy layout things, potentially things that don't fit into the C model at all. We're going to have the best support we can for kind of pre existing C binaries, but they're going to be much sharper limits there. The best experience and kind of our top priority is you can compile your code with Clang, which means that we can compile your code with this kind of joint Clang plus the Carbon compiler and actually give it custom semantics. Custom abi, lay out everything just right so that there's no copy. We don't expect any realistic runtime overhead here. The overhead we expect is compile time.
Kevin Ball
Right.
Chandler Carruth
We want Carbon to be a really fast compile time environment, but we are going to take a compile time hit when we reach into C. We kind of have to.
Kevin Ball
All right, that makes sense.
Michael Rosenthal
Capital One's tech team isn't just talking about multi agentic AI. They already deployed one. It's called Chat Concierge and a simplifying car shopping using self reflection and layered reasoning with live API checks. It doesn't just help buyers find A car they love. It helps schedule a test drive, get pre approved for financing and estimate trade in value. Advanced, intuitive and deployed. That's how they stack. That's technology at Capital One.
Kevin Ball
Any other nuances related to this sort of interop layer and how these things are working together?
Chandler Carruth
I mean, there are so many nuances here. I think one thing that is really useful to think about is what does it take to do this kind of interrupt? Because I don't think it's obvious when you're kind of looking at it from outside the programming language of the compiler world. People always like to think about really complicated things. Let's think about simple things. What if you have a boring old fashioned abstract class in C with virtual types and we're doing object oriented polymorphism? I know it's not a trendy thing, but it still is a thing that people do. There's a lot of code out there that does this, right?
Kevin Ball
Yeah.
I mean, if you're maintaining millions and millions of lines of code, I'm sure some of them are going to be utilizing this. They were written a while ago. You don't get that overnight.
Chandler Carruth
You don't get it overnight.
Kevin Ball
Right.
Chandler Carruth
And so you've got these things in there and you need to do this. Well, this means that in order to use, you've got an API and it's going to accept a pointer to this abstract base class and the API documentation is going to tell you, well, you call this by deriving from that, overriding these virtual functions with your specific behavior and then passing your object. That's how my API works. But think about what this means. This means that in Carbon we have to be able to derive from a C base class, get the virtual functions, override them in Carbon with virtual functions that you can call using the C vtable because there's some code that never saw your Carbon instance. Like you can't customize this and then you have to hand that back to C and the client has to do the right thing. Even though it no longer knows there's a Carbon type under the hood. It just has an abstract base class pointer and a vtable and it's like, I don't know, I'm going to do a, do a virtual function call. It'll get there eventually and we have to make all of that work. And so, okay, so there's a lot of compiler infrastructure needed just for this.
Kevin Ball
Right?
Chandler Carruth
There's also language implications. This means your programming language needs to have inheritance. Rust doesn't have inheritance. Go's Inheritance doesn't look anything like this. What language are you going to be able to model this kind of dispatch? This is one feature.
Kevin Ball
Yeah.
Chandler Carruth
We can keep going through all of them. Every aspect of Carbon's design actually has to look at C's design and think about like, okay, what features need to show up in Carbon from C through Interop? What's the model we need to have for those? How do we make that work? And this adds so much complexity. If you look at modern programming languages, basically none of them have overloading or variadics the way C does.
Kevin Ball
Right.
Chandler Carruth
The only modern programming language that's even tried to do variadics in recent years is Swift. They have an incredibly cut down minimal version. And they added it like in what, Swift 5, Swift 6.
Kevin Ball
Right.
Chandler Carruth
Like they didn't add it in Swift 1. We have to have variadics and like complex, wildly fancy variadics on day one, because half of the C APIs we want to interoperate with are variadic APIs, their std format and all of its friends, all these different APIs that use all of these C features. This means we have to start off with both a very specific feature set and a very large feature set to have any hope of success. And that is a real challenge. We've been working at this for a few years now because it's so hard to build up this body of design that can actually support the Interop. I think it's hard for people to see the design impact there.
Kevin Ball
Yeah. Well, and this leads us into another area of conversation that I think will be interesting, which is about the language itself.
Right.
Like there's a set of things that you have to implement in order to have C interopt. But also part of your goal here is to get away from some of the C isms and build in some new modern things. So what does this language bring us?
Chandler Carruth
Great question. So there are a few things we've already talked about. One of them actually. One of them is fast compile times. I know I harp on it a lot. It seems like it doesn't actually matter. We have like build servers and build far. It matters so much. Like, it is so painful to sit there like, okay, back up. We measure compile time for C code in minutes. So I want you to think for.
Kevin Ball
A minute, all of you using vite that get your millisecond turnarounds in the browser, seeing the UI difference. Yep.
Chandler Carruth
Let's think. What is a computational activity that we do in the modern world on modern computers? That takes minutes.
Kevin Ball
I mean, look, we're in the LLM world now. So there's more and more of those.
Chandler Carruth
Going on asking, like this LLM, this billion variable LLM to synthesize, like the work of Shakespeare or some nonsense, whatever it is that we're doing. A video, right? Synthesizing a video from a neural network is the kind of thing that takes minutes. We're compiling text. We're compiling like a few hundred thousand lines of text, and we're waiting minutes for it. Like, they have played us for fools. This is absurd. And so I get really upset about compile times. Like, we're not even in the right order of magnitude. We shouldn't be measuring compile times in minutes or in seconds. You said it. We should be measuring it in milliseconds. We should be measuring it in things that are kind of interactive speed. We need to get down to that. So that's the first thing we want to bring. But if we look deeper into the language design, one of the biggest things we want to bring is we want to bring some path to kind of the modern requirements of programming languages.
Kevin Ball
Right.
Chandler Carruth
The big one is memory safety. But it's interesting to kind of decompose. What do you actually need to achieve memory safety, particularly for high performance? Like either you have to sacrifice performance and have a garbage collector reference count or something like that, or to get memory safety and all the performance. Rust has really taught us what we needed here. We need a parametric type system, and we need to be able to parameterize the type system with all of the information that kind of enforces correctness, enforces safety of lifetimes and ownership and all of these things.
Kevin Ball
Right.
Chandler Carruth
But that parametric type system is kind of the elephant in the room when you get into the PL space.
Kevin Ball
Right.
Chandler Carruth
Because C's parametric type system are C templates. And templates aren't super fun. They don't give you good error messages. It's hard to program with them. They don't have API boundaries, and they also have incredible code size cost and compile time cost. Every programming language that is trying to achieve this kind of guaranteed compile time memory safety is doing it by having definition checked. Generic programming facilities. Rust has generics that are checked at definition time. Swift does. They're adding ownership and lifetime things to Swift. Now, if you look at the predecessors of Rust, all of them modeled this in the type system. And the nice thing about doing this without templates is they can actually avoid generating a different version of every function for every lifetime equation that it ever shows up in we already have enough duplicate code in C. We don't need to like multiply that by 10 or more to get memory safety. But that means we have to go back to one of the most controversial features that was ever attempted to be added to C, the original C concepts. Back before C11, Doug Greger, the eventual designer of Swift, tried to bring this kind of definition checked generic programming model to C. It hit a lot of problems and eventually it hit just insurmountable problems. And the insurmountable problems it hit were tied to backwards compatibility issues. The entire design of the C standard library needed to change and evolve to leverage this new type system, right? And that was too much of a change. It broke everything. It would have set us back another 10 years. And so the committee had to pull it out. We got concepts, but we didn't get the concepts that actually give us this feature. We got concepts that work with the existing design of C that's great for that design, but it doesn't give us the parametric type system that memory safety needs. So the very first thing, and probably the biggest single thing that we're adding in Carbon is this idea of definition checked generics. But because we're coming from C, we don't get to just add, we also have to innovate. We have to build not just a definition check generic system, but we have to build one that includes templates because of Interop. So we have a generic system that can both do definition checking and allow future kind of lifetime memory safety facilities, and supports raw templates instantiated just like in C, with all of the quirks and oddities and behaviors that kind of are necessary to support Interop. But now you get to start moving away from those quirks, right? You get to incrementally say, like, you know what, I actually do have an API that this generic conforms to. You can remove the template from it, we'll check it, right? We'll actually give you code size benefits, we'll give you ergonomic benefits, the beautiful error messages, all that stuff will start to arrive and you get to adopt that incrementally. And I think it's going to be absolutely amazing to have that for kind of library authors, for anyone writing generic code. To be able to move out of the template world and into kind of this checked generic programming world, but not leave all of your dependencies behind is going to be amazing. And I think that's probably the single biggest. Like there's a banner feature that really we already have. It's going to be that one and the one we're working on next. And we just kind of announced that we're actually getting ready to start on designing the memory safety pieces on top of that. And so over the course of this year and next year, I think you're going to start to see how we're going to layer memory safety as well. And so you both get this more powerful type system and then more powerful safety system as well.
Michael Rosenthal
We're hiring. This is Michael Rosenthal, chief executive here at Software Engineering Daily and we're looking for a director of Operations to help run and grow our day to day operations. If you're highly organized, self directed and familiar with the world of software, you may be who we're looking for. And if you thrive in high autonomy, we linchpin positions and want to learn the ins and outs of a bootstrapped tech centric business. This may be the role that you're looking for. To apply, send Your resume and LinkedIn profile to careersoftwareengineeringdaily.com More details can be found in the show Notes.
Kevin Ball
Can we maybe talk about what that migration path looks like? So say somebody's built out a bunch of stuff in templates and they want to start migrating over to Carbo generics. Like, what does that look like?
Sure.
Chandler Carruth
So the first thing is to use something like generics, you need new language constructs, right? And the whole reason we're doing Carbon is that we didn't want to have to try and fit all of these new constructs into C. Technical debt, the complexity, it just didn't make sense. So the first thing you do is you basically take your existing design as it is and you just translate it into Carbon.
Kevin Ball
All right?
Chandler Carruth
This doesn't give you magically better everything. We can detect easy cases and be like, we can prove that this didn't need to be a template. We can do some easy cases. But we always have this fallback of like, nope, we're going to faithfully move your C code into Carbon. That's going to be fairly automatic. We want that to be kind of click button in the ide, like as automated as conceivably possible. Once you're there, right, you don't have the better code yet. I mean, there's syntax and keywords. We can talk about that if you want. But like once you're there, then you can start incrementally doing this. And so the first step is you can add a constraint to your template, right? And C concepts allow you to somewhat do this. But when you add a constraint to a template in Carbon, we're going to check it more thoroughly because we're going to basically check, if this weren't a template, would it fail? It's still a template. We're going to give you that behavior, but we're going to actually, like, validate that. Yes, you actually abide by that constraint. And so as you add those constraints, you can then propagate them, because you have to teach everyone who's using your template to satisfy that constraint. You can propagate them slowly because it's still templates. It's okay if there's a layer that hasn't yet kind of documented that, it satisfies that as long as the template did work, you're fine. Once everyone does, you can remove the template. And now that constraint isn't just checked to be correct, it's also required. And now it can be required and we can leverage it. And so you basically have this free way of adding a new feature, right, that doesn't break anything. There's no ordering dependencies or anything like that. And once you kind of get all of a particular API to use that new feature, you get to restrict it a little bit and kind of start leveraging the new semantics, right? And the important thing is this is incremental, right? There's one big bang thing, but that one doesn't do anything exciting. It's designed to be boring. And then all the exciting pieces are small incremental changes that you can kind of do independently, API by API, almost line by line, right? And get to the point where you're trying to get there. And this pattern, by the way, is going to repeat.
Kevin Ball
Yeah, no, I love that, that you're thinking about, what does that migration path look like? And it is the type of thing you do anytime you're navigating legacy code, right? You're like, okay, let me get a nice clear boundary around this. Let me move it into the new place without any functional changes, and then start incrementally bringing things up to piece by piece.
Chandler Carruth
Great analogy, right? Like, I love actually talking about legacy code maintenance, because that's really what inspires a lot of this. So how many times do you, like, go look at legacy code like, oh, what's the first thing you do? Seriously, what is the very first thing you do? Like some really gnarly code you find, is this tested?
Kevin Ball
That's my first question.
Chandler Carruth
Okay, start writing tests. What's the second thing you do? Second thing, the first modification to the code you do.
Kevin Ball
First modification I would do is try to build an API boundary around it if it.
Chandler Carruth
Cause before that you reformat it.
Kevin Ball
Yeah, okay, fair enough, fair enough.
Chandler Carruth
Yep. Everyone goes and reformats it. They're like, oh, I don't. I'll run my format tool over this.
Kevin Ball
Right?
Chandler Carruth
Yeah.
Kevin Ball
No, that's a good point.
Yep.
Chandler Carruth
That's how easy we want it to be to start adopting carbon instead of running your format tool. Oh, this is old C code. I'm going to carbonify it now. I've got it in carbon. It's not beautiful code yet.
Kevin Ball
Right.
Chandler Carruth
But just like the formatter tool, at least put it into the pattern. I'm used to it. Gave me kind of the flavor I expect. Same thing now. Okay, so this is just crufty carbon code now.
Kevin Ball
All right.
Chandler Carruth
And I have all the tools I need to start making it less crafty.
Kevin Ball
Love it. Okay, so generic types, generic types, parameterized types, all these things. That's a big thing. What else makes Carbon distinct? What are the modern language features you're bringing into it that you didn't have to bring from C but you want?
Chandler Carruth
So what are some big fun things outside of generics? Honestly, I think in terms of big things, if you look at this from the lens of C, right, And what feels new coming from C, I think generics and the safety things are going to far and away be the biggest new things. I don't know how many new things. We don't have any plans for other new things because fundamentally, the motivating thing for all of this is really memory safety, because that's the proximate problem bearing down on us.
Kevin Ball
Right.
Chandler Carruth
Generics are only even in there because we think they are a critical technical dependency of the only way we really know how to address memory safety at the highest performance level. Beyond that, we're not trying to innovate. So in some ways, this is a weird thing for a programming language. Like, we don't have a goal to be new in that way. Instead, what we really want to do is systematically make the existing features of C better. So let's look at inheritance. I want to go all the way back to inheritance. I know maybe it's old school and all of that, but C inheritance is kind of a nightmare, right? Like, you have inheritance and you have virtual inheritance, you have multiple inheritance, and you have distinct multiple inheritance without virtual inheritance, and multiple inheritance with virtual inheritance. I don't know if you've ever played with those parts of C. Like, there are dark, bizarre corners here. And people use these things, right? They use them heavily and they really Rely on them. But the tools are not good. The use cases are. It's the tools that we need to make better. And so we want to try and look at these use cases and just come in with a better version of the same tools. I don't think this is novel, but I do think that's going to make a much better experience. So we have single inheritance and carbon, right? Because that's the one that you can do kind of dynamic dispatch over in a way that's really easy and straightforward. But all of the uses of multiple inheritance, they are real uses. And so we want to try and recast the same core ideas. Which is typically kind of designed by composition. Like, well, I want this type to have these four facilities. So I have this base class that I'll just like inherit from and it'll give me some methods and fields that provide those facilities. It's compositional design. There's a good way to do that in modern programming languages. They're called mixins. I mean, you can say that we're adding mixins, but we have mixins in C. That's what multiple inheritance gives you, are mixins. It's just really, really painful. So what we're going to do is we're going to have mixins. We're going to target exactly the use cases we see on C, make sure that they work. They're easy now, they're clean, they're unsurprising. Everything is just like, oh, well, yeah, of course that works wonderfully and that's going to repeat. Coroutines is another place where I think we have just so many opportunities to make the experience smoother, cleaner, more enjoyable for users. Error handling. I think we can do error handling so much better. Here's a place where we may actually remove some things. I'm not a big fan of exceptions. I am a big fan of performance. Maybe we can come up with an error handling system that gets the best of both worlds, right, that gives you kind of the best ergonomics we can manage, but also has the best performance. And that might actually be taking a little bit of some things. And exceptions might be taking other things from kind of rust style, result types and kind of the monadic transformation that they do. There are a whole bunch of tools we can try and bring together. I don't think of these as bringing something really new to the language. Everyone can already do error handling in C. It's just a pain. We're going to try and make it easy, super, super friendly to users, really easy to kind of compose and use all over the place. And that's kind of outside of memory safety and type check generics. That's really the focus that we have is just take what's already there. But let's make it principled, let's make it understandable, let's make it really easy and fun to use.
Kevin Ball
Yeah, well, and I think it makes sense, right? Still, there are so many hundreds of thousands of people writing C code because it fills a niche, despite how painful it is, despite how old and crufty the language is, despite how they have to grapple with multi minute compile times. If you can capture all those benefits without the costs and bring the development experience up to the modern world, there's a huge opportunity there.
Chandler Carruth
Maybe there's. Let's dive a little deeper. So like coroutines and I don't know, virtual inheritance, all these are kind of like big features. I think maybe where there's more interesting things that even seem like that we're adding something is if you go, if you zoom way in to the minutiae. Because when you're talking about what are the use cases we support and to your point that we reach for C despite it's paying for it, it's for incredible high performance that is often a problem solved in the minutia in the details, that's a place we can actually start innovating some. So here's something that seems like this should be a simple thing and the smallest thing in the world. In C, how do you pass an input parameter to a function?
Kevin Ball
Right?
Chandler Carruth
In every programming language other than C, there is one obvious answer and it is the way you pass input parameters to the function on day one of learning the language. Like the first function you write, you use the correct way to pass input parameters to the function. Every programming language, but not C. So in C we have const references which seem like a really good way to pass things as inputs, right? It says, hey, don't mutate this, but you get reference semantics so you don't have to dereference it everywhere. You can even pass temporaries like you can compute a new value in the argument. And that's fine, it'll pass as a const reference, no problem. But there is a problem const reference under the hood is a pointer. And this is very fundamental in C. You can't not implement C with a pointer for a const reference parameter. You can take the address of a const reference parameter inside the function, you can return that address to the caller. It's required to match. So, like, you don't have any flexibility about this. It has to be a pointer under the hood. Pointers have cost. That means every time you access a const reference parameter in C, you're indirecting through a pointer. Now, some of the time, this is exactly what you want. You had an enormous class, some data structure that you were passing in. You don't want to make a copy of it. You, of course, want to just give a pointer to the giant data structure you allocated somewhere and then access it. This works great. But what about integers or, you know, something that comes up every now and then in really high performance settings like floating point numbers or SIMD vectors? You don't want a pointer to like a SIMD vector that you're like measuring the exact cycle count of your CPU processing the data to hit a frame rate budget in a video game. That is not okay. It's not acceptable.
Kevin Ball
Right?
Chandler Carruth
And so you have to, you don't have a single way to pass an input parameter in C. You have to think about the type of the parameter. Like, well, hold on, is this like a small parameter that I don't want to have a pointer to, or is this like a big parameter where I want a pointer and that tells you whether you pass by value or you pass by const reference? And if that's not bad enough, I mean, I'm already horrified because you've just told every programmer that for like the simplest thing to do in a language, pass an argument to a function, the simplest thing, you have to think carefully and make a decision. I don't know about you, but, like, decisions are expensive. Like, writing code is not that expensive. Making decisions is really expensive. And we have to do it every function signature. But it's worse. Like, it's not even that bad. It's much worse than that. Because of generic programming, I may not know the type of that parameter. How do I know? Yep, yep.
Kevin Ball
How do I know which one to do?
Chandler Carruth
And in fact, there isn't a correct answer in C. And I mean, so here's something very fundamental and this is something we definitely can solve. So we're going to have a way of passing inputs, parameters, and carbon. There's one way. It's also by chance the shortest way of passing a parameter instead of one of the longer ways with a const reference.
Kevin Ball
Right?
Chandler Carruth
And so it's going to be convenient, easy. It seems like such a small thing, but every one of these adds up in performance cost. And so one of the interesting things is, I think when people Start migrating from C to carbon and start using carbon. We're actually going to be able to deliver performance as well as safety.
Kevin Ball
Right.
Chandler Carruth
It's not going to be just one or the other and the performance isn't going to be because a magical new compiler optimization is unlocked. I mean, I would love it if we did that, but I don't have any magical optimizations left on the table. They're all out there doing stuff already on C. What we do have are little things and these little things I think really add up. And the little things like getting your input parameters right. I don't know if you like. See, I gave a talk about STD unique pointer in C, which is like one of the most basic types. It's like I allocated some memory on the heap, but I own it and when I'm done with has to be freed.
Kevin Ball
Right.
Chandler Carruth
Simplest type in the world, it already is a pointer to memory on the heap, but if you pass a unique pointer as a parameter, you don't get a pointer parameter, you actually get a pointer to a pointer. And again, could we fix this? Possibly. But fixing this is a backwards incompatible change the standards committee and C are just not in a good position to do.
Kevin Ball
Right.
Chandler Carruth
And I don't want to say that they're kind of wrong to not make these changes. They just have a different set of priorities. Their priority is backwards compatibility, Right?
Kevin Ball
Absolutely. I mean, we see this all over the place in software. Right. You see this in the new JavaScript runtimes. Right. If you can ditch some backwards compatibility, you can build something that's way faster.
Yep.
And I mean, actually, as you were talking about, though, just one way to do it and how that enables performance, it had me thinking about golang.
Right.
Like, go does this very well. Super simple constrained language, very easy to write performant code.
Chandler Carruth
Yeah. You don't have to like think about, oh, have I made the garbage collector's job hard? It's like, no, no, no. It's made sure that the normal thing you do works well. Like works well with the garbage. It's a beautiful language in that way.
Kevin Ball
Well, and in the kind of world we're in now where more and more of the actual code is being written by coding assistants and we're the ones making the decisions and then telling it to do it, having one way to do the thing you want to do is also an incredible unlock in terms of productivity.
Chandler Carruth
Absolutely, absolutely.
Kevin Ball
So let's maybe talk about a slightly different thing about. So this is an early stage project, as I understand. It's an open source project and I saw the governance structure and I thought that might be interesting to talk about briefly, especially because I saw you have two big roles. I saw leads and a painter and I hadn't seen the painter before, so I kind of wanted to get your take on how is this being governed and what is that painter role.
Chandler Carruth
Sure. So the first thing just to back up and say a little bit of context about the governance. I think it's important to really understand what we, what we're trying to set up to do here.
Kevin Ball
Right.
Chandler Carruth
So a critical thing for a lot of users of C is that it has a real governance model. It's not owned by one company. It's something that they can rely on and that they can participate in that governance they can contribute to. Like there are a lot of users of C who want their voice to be heard and be able to have a say in where the language goes. And so we needed, when working on Carbon, we really needed to make sure we were setting ourselves up for, for a success path there. I've been in a lot of open source projects and every one of them, when they didn't start off with a governance model and they tried to add it later on, it was chaos and tragedy and pain and suffering all around. Introducing governance late, which is of course when you finally need it, is almost always a painful process. We wanted to try and address that and so we decided to front load having a governance process and a governance system. Even though Carbon is a tiny little experimental project, it probably doesn't need half the governance infrastructure we've put in place. But now is when it's easy for us to put it in place. And so we've done that. And the whole thing is we're really aiming for the long term here. We want to be set up in a good place and we are really aiming to be open source in a very fundamental way. We want this governance to be one that can evolve, that can be increasingly community driven and not driven by any one company. And we want to have a clear cut and explicit path to get there rather than trying to do it after the fact, or worse, not doing it because we didn't plan for it. So that's kind of what led us to the governance structure. The flip side is we do need the governance structure to move fast. It is still an early stages project. We don't have the luxury of having a very slow moving, deliberative kind of governance model. The balance we struck here was to basically have three leads, don't want to have Benevolent dictator for life model. Setting aside other problems with it. It creates a single point of failure. You know, if someone's out sick, how do you make progress?
Kevin Ball
Right?
Chandler Carruth
We really don't want to get stuck there. And so we're like, what is the least amount of overhead we can have while not having kind of this critical failure mode? We tried actually in the earliest days of the project, tried setting up kind of a more committeeish structure with like eight people. And there were votes, rules about how we make progress. And it was slow and burdensome and like, it didn't work. Even at the tiny scale, it didn't work. So we kind of distilled it down to like, no, look, there are three leads. That's enough to kind of rapidly get to consensus, right? It's enough for us all to develop a really strong rapport with each other so that we can iterate rapidly, actually have incredible trust. Usually one lead is enough to make a decision. The other leads are available, they'll push back if it's the wrong decision. But we don't even have to necessarily synchronize if we're like, no, this is an uncontroversial thing or in an area we've talked about. And that makes it super rapid. It even makes it better. Because now if one person's making decisions, then go on vacation. Decisions keep happening. It ends up working out really well. Now, to make it last long term, one of the tricky things is you can't just have the same people be leads forever. But again, in the early stages of a project, you can't just rotate leadership and expect to ever get to a good result. So what we've basically done is said in our leadership, in our kind of governance model, when the project reaches a level of maturity, we're going to institute term limits and we're going to basically start rotating through the leadership role. And we said that that can't arrive after a particular milestone. So we don't really care when it starts. But we have a bound, an upper bound on how long before we start rotating. And then we'll probably do kind of nice overlapping terms so that we're not churning all of the leads all at the same time. We're going to rotating through them. We'll end up building up an emeritus group of leads so that if someone has a family emergency or a change of job or something, we can just rapidly get an emeritus lead to step back in. We're going to allow people to come back right after they leave. So it's also the stakes are lower right. And people feel comfortable stepping down because, hey, they're going to. They're going to get to go and, like, recharge for a while and then come back in if they. If they're still super motivated here. So that's kind of how the structure evolved and how it tends to work. All the decisions we make are public. We always also have to switch hats. So the leads are often technical experts in the community, but they can't be technical experts while they're making a decision. If they have an opinion about the right technical direction, they have to go and state that publicly as part of the discussion about that decision first. And then we can kind of consider that statement as leads and maybe make a decision that reflects it. And that kind of forces us to be open to engagement with the broader community. And it defends a little bit of the small size of leads, because there's not. Honestly, there's not a lot we can do as leads. Mostly we just have to participate as technical experts. And then when there's a question and all of the positions have been aired, they're all written down, everyone understands them, we have to make a call. That's actually the only thing the leads really do. Even that's a little bit too much. There are a bunch of calls where, like, it doesn't matter. And this always bothers people in programming languages because people get really attached and, like, everything matters. Like, the comic introducer character matters to some people. I get it. Like, it's near and dear to your heart. You see it every day, all day. As an engineer, I understand that. But realistically, we're not going to have kind of weighty decisions every time. That's where the painter kicks in. At any point, the leads can simply say, we have a set of options, which there are no technical reasons to choose between.
Kevin Ball
Right.
Chandler Carruth
Maybe we've discarded a bunch of other options for technical reasons as leads. Fine. But there's some, and it's not one. There's multiple options left, and there's no technical reason to pick one or the other. When that's the case, they can ask the painter. And the painter is basically just a tiebreaker there. Like, all right, go left. Paint the bike shed blue, right. You've gotten rid of all the paints that are going to run, that are going to not weather well. The paints that cost too much. You've gotten rid of all of those, but you still have three different colors. The painter's there to be, like, blue or whatever color is appropriate.
Kevin Ball
Right.
Chandler Carruth
For purely aesthetic things, we do have to make decisions. Still, that's where the painter role kicks in.
Kevin Ball
I really like that because it eliminates one of the most common failure modes I've seen in these sort of consensus based decision making structures is when you get to the point where there really isn't a best answer and you're just like, well, how do we decide? And this person has one opinion and that person has another opinion, but it's nothing but an opinion.
Chandler Carruth
And here's the funny thing, Painter doesn't make any decisions. I was stunned by this. I mean, I put myself as the painter. I freely admit I expected to get to make a bunch of purely aesthetic decisions here.
Kevin Ball
Right.
Chandler Carruth
Almost none. Like, so close to zero. It staggers me that's not the actual effect it has in practice. In practice, what this does is it gets everyone to stop arguing the aesthetics and actually state the underlying technical reason why one option is preferable to another. And it does so in a way that's so much less combative. Like, because if you try and tell people, like, that's an aesthetic argument, stop making it right, that doesn't work. Like, no, it isn't. It matters to me. I really like blue. Okay, it doesn't work. But if instead you say, well, if that's an aesthetic argument, then we have a process we're going to use over here. All of a sudden, now they're motivated to figure out why they actually prefer one based on technical rationale. And the amazing thing is we usually find technical rationale. Like we almost always find a technical reason why choice A is actually the best choice. It's not aesthetics, it's not zero, but it's really close to zero. How many times it's like, yeah, either spelling is fine. So that was actually a really interesting thing to me. I think that the painter role is effective even when it is never used.
Kevin Ball
Yeah.
It creates a different set of structural incentives.
Chandler Carruth
Totally different set of structural incentives, and ones that feel much more friendly.
Kevin Ball
That's delightful.
Chandler Carruth
Like, you can be happy about being forced to find the technical underpinning because it's not like someone's devaluing your judgment. Yeah, that's great.
Kevin Ball
So let's talk a little bit about language status. I saw that a goal for last year, 2024, was having a working toolchain up through the C interop that we talked about today.
Chandler Carruth
Yes.
Kevin Ball
Did it happen?
Chandler Carruth
No. I mean, you're asking, did a software project, like, hit all of its deadlines?
Kevin Ball
No, I didn't.
Chandler Carruth
And the answer is, of course no. No, it Didn't. As per usual, our ambitions exceeded our capabilities. Everything is harder than it looks when you start. We did get a working toolchain. We have a remarkable change in toolchain at the start of 2024. The toolchain was as nascent as you can imagine. We'd done most of our work actually prototyping in kind of an interpreter demo space instead of in the toolchain. And so the toolchain was just almost nonexistent. At the end of the year, one of the kind of main developers on the toolchain actually got through, I think, 13 days of Advent of code in Carbon. Now, most of them included patches to the compiler, which I just said is not really the ideal way to do advent of code, but didn't make it through technically. There was someone who did one advent of code challenge on the old interpreter demo in Compiler Explorer on the website, like writing TypeScript code to upload the advent of code problem data and extract the result. I don't know how they did this. That was amazing. But we got 13 admin of code days done on the toolchain with a very minimal number of compiler patches. It's actually a very functional toolchain from a toolchain internals perspective yet. But we didn't get to the point where it's starting to be more functional for kind of users of the language or people evaluating the language, largely because we still need Interop. We got Interop started, but we didn't make much progress on Interop last year. And by started, I mean we taught the toolchain to have clang alongside it.
Kevin Ball
Yeah.
As we got into. Right. There's a lot of detail and nuance that goes into that. So what are things looking like for this year? I saw the next target, big target beyond that was 0.1. Or is 0.1 when you can do that, what does the next three, six months look like? And if somebody's excited about Carbon, when can they start digging in?
Chandler Carruth
It's important to understand the sheer timescales here. There's no way that 0.1 happens this year. I wish it could. There's just way too much to do before we can really call it 0.1. If you look at our 0.1 definition, it's actually very ambitious. We want 0.1 to be kind of close to production quality for the purpose of evaluating Carbon within a real C environment.
Kevin Ball
Right.
Chandler Carruth
Like, I have a real C code base and a real use case and I want to try it out and see how it works in Practice. There's tons that we need to do to get there. So this year our goals are twofold. One, we're going to try and get C Interop from kind of the nascent state, right, where, like, we can load C and build that AST all the way to actually doing Interop. Specifically, we love to kind of do Interop without templates, so no template instantiation, but like that fancy virtual inherit, like virtual dispatch stuff, moving objects back and forth across that boundary. That's our real goal for Interop for this year, because that's going to get kind of the foundations of Interop in place. And this includes incredibly hard stuff.
Kevin Ball
Right.
Chandler Carruth
Think about types with operator, like with not just function overloading, operator overloading. One thing we want is to actually map, like your operator plus overload in C. Let's write A plus B on your special vector type. We want you to be able to write A plus B with that special vector type in carbon, and that carbon plus maps all the way back through to find your C. So this is actually still pretty ambitious. And then the second thing is we've gotten feedback already that we really need to accelerate, kind of telling a concrete story about how memory safety fits into this picture. So far, it's been fairly aspirational and there's a lot of hand waving. We've got to make it very concrete, very specific. We probably won't get past kind of slideware describing the design for memory safety, how it works, how you can migrate towards it, but we at least need to get to that and a very concrete version of that by the end of the year. The team's also grown a little bit, and so I think we actually have the ability to kind of pursue both of these over the course of this year.
Kevin Ball
Awesome. Well, we're pretty close to the end of our time here. Is there anything we haven't talked about that you want to make sure folks are left with?
Chandler Carruth
We've talked about all of the amazing and good parts of Carbon, but what about the bad parts? A lot of people, I think, are a little nervous, like raising bad parts. But I actually think these are good to talk about too. I can tell you the bad parts I'm hearing, but any bad parts I think would be great to talk about.
Kevin Ball
Yeah, dive in. What are you hearing about?
Chandler Carruth
One that I hear all the time is, why on earth did you change the syntax so much? What is this effing keyword nonsense? Why are there colons everywhere? People are really frustrated by that. And a couple of things. First off, you're not alone. I'm actually really frustrated by a couple of the syntax choices myself. This isn't exactly how I had hoped Carbon would end up looking. I think people are really frustrated because it seems unmotivated. It's not that the syntax changes are necessarily bad, but it seems unmotivated. I think that's actually an important thing to address. So first off, there are two parts to any motivation you've got. Cost and benefit. The first thing I think people mistake is the cost. Syntax is relatively cheap now. I don't mean to say it's free. Some people are like, oh, it's just like the compiler handles, that syntax is free.
Kevin Ball
No.
Chandler Carruth
Humans also have to read code. Asking humans to like, see different keywords is a cost, but mapping from one set of keywords to another in fairly similar positions or adding keywords to a structure that is already relatively similar is. Is something that humans can do it fairly easily. If you look at kind of programming languages that have done that, that didn't cause massive problems.
Kevin Ball
Right.
Chandler Carruth
The complaints about Python 2 to 3 were not like new keywords in existing structures, it was that you needed to change the structure in some way.
Kevin Ball
Right.
Chandler Carruth
So while I understand that there's kind of an emotional immediate reaction when you see this, we don't have any evidence that the cost of this is going to be especially high for the humans. But what's the benefit? The benefit is, I think, really surprising. We keep finding places where having the simplified syntax, the simplified grammar, actually helps make our compile times faster. A lot of people are like, parsing is a solved problem, none of the compile time is spent there. And like, yes, a little bit. But also know that these aren't as separable of problems as they seem on the surface. We find that the grammar structure of the language, we end up using it inside the semantic analysis. That's doing type checking, that's the expensive part of the compiler. When we have the wrong structure, we have to waste time and waste resources actually doing that checking. And so I think it's a little bit more important than people see. And so the big thing I would love to say is just like, we do hear you, like we are aware of the cost here. It's just that when we really evaluate it and when we play out for the long term, the changes do seem to make sense. And we're constantly evaluating that trade off. We may even have the wrong trade off. A fun thing. We used to actually have a different grammar in an important way. We used to actually have in variable declarations you do like variable type, colon name equals and your initializer, which is a little bit closer to C's type space name equals initializer. But when we put the colon in and that was the first thing we did, that was to make the compile times faster. It actually significantly improves how easily this parses having that colon in there. But when we did, it started to look like declarations in TypeScript and in Rust and in Swift and like in all these other languages, but in every single one of them, the type and the variable name are in the opposite order. The variable name comes first, then a colon, then the type. Lots of good reasons why they all evolved that way. I was very reluctant to make this change, but we finally decided like having a colon, but being different from every language with a colon was even worse for programmers than having the order the same way around. And it was a hard trade off that we made. And every time we're going to keep making those trade offs as like we are going to think about it as hard as we can and we may even change our minds if carbon 0.1 comes out and everyone's like, this language is great, but you all have to get rid of this FN keyword. We're going to go revisit that trail. We are going to respond to this, but we have to be careful. We can't just kind of arbitrarily copy syntax from C. We have to think about each and every one of these decisions.
Kevin Ball
Well, it sounds like if I'm not mistaken, those arguments are happening in public. People can go and see the ways that you're deciding those trade offs and kind of the justification of hey, this is aligning with all these other languages that have this type of syntax or hey, this is improving our performance on the parsing step by this much which has these impacts.
Chandler Carruth
Yeah, there's a public issue on GitHub from when we switched the order of type and variable name, where this is specifically called out as what motivated us to make that change.
Kevin Ball
Well, and I harp on this a lot, but like we are in a new era when it comes to code generation tools and the more it's going to be similar to what other languages expect, the more your generation tools are just going to work and it's going to be easier to adopt not only for, you know, programmers coming from non C backgrounds, but also for programmers adopting tools trained on a wide range of languages, all of which behave one way. And if yours is the odd one.
Chandler Carruth
Out, it's going to be awful.
Kevin Ball
Right.
Chandler Carruth
And there are lots of other complaints, but actually we actually touched on most of the other complaints. I think, like a lot of people are worried, is this vaporware? Is this ever going to show up? We talked about the timelines. There, you know, a lot of concerns around this Interop thing. It can't work. Like, you can't actually make this work. That's actually why Interop is such an urgent goal for us. That's why we're prioritizing as highly as we are. We think that really we have to show our work here. We have to basically show a working version of this. It to be compelling and believable and we understand that we're going to actually come there with proof in the pudding. I think memory safety, like, why are you not thinking about memory safety? I think maybe one interesting thing is a lot of people don't understand why we started with the memory unsafe version of Carbon. It's a weird choice in this day and age to start there. And I actually agree it is weird. The key realization for me was that all of the C code we need to interrupt with is also unsafe. It's not that we have the flexibility of choosing here. We have to start off with the kind of primary reason we exist, which is Interop with C. We have to make sure that that works. We still have to make sure we can add memory safety to this. Like if we can't have memory safety at all, none of this is going to work. All of our programming languages are going to end up having to have some kind of memory safety. And so it is, it is absolutely like a necessary goal for us to get to. But if that were our only constraint or our primary constraint.
Kevin Ball
Right.
Chandler Carruth
That's why people are using Rust. Rust is a great option already. That's why people are using other languages. They start with that constraint. The whole idea of Carbon is what if we start with the constraint of building off of C? And that means fundamentally building off of unsafe code.
Kevin Ball
Right.
Chandler Carruth
And unsafe code patterns. So we have to support those as well as we can and then layer memory safety on top. I mean, we still have to prove that one out and that's one of the things we're working on. But that's kind of the underlying motivation. It wasn't like, ah, we don't care about this memory safety thing. It's overblown. Totally the opposite. It's that we care about how we get that memory safety on top of existing C code.
Kevin Ball
That sounds like a great final cut. So let us hit stop there.
Podcast Summary: Software Engineering Daily – Carbon and Modernizing C++ with Chandler Carruth
Episode Information
In this episode of Software Engineering Daily, host Kevin Ball engages in an in-depth conversation with Chandler Carruth, the creator of the Carbon programming language. The discussion centers around Carbon's objectives, its interoperability with C, unique compiler architecture, language features, migration paths from C, governance structure, and the future roadmap of the language.
Chandler Carruth, a seasoned software engineer at Google, shares his journey leading to the creation of Carbon. His initial frustrations with C’s limitations, particularly in handling large codebases and slow compilation times, prompted him to explore deeper into compiler technologies and ultimately spearhead the development of Carbon.
[01:34] Chandler Carruth:
"Working on the C code base was painful. The tools were bad, the experience was bad, and it became an overwhelming problem that we needed to solve... And that's where we started working on Carbon."
Carbon was conceived as a successor to C, aiming to integrate modern safety features without sacrificing performance. Chandler emphasizes the need to modernize C to maintain and enhance Google's extensive C codebase and the broader industry reliance on C and its derivatives.
[01:34] Chandler Carruth:
"We need something that we could bring all of that code along with us, but get the kind of radical transformative change we're hoping for here."
Kevin Ball probes into why Carbon opts for deeper integration with C rather than leveraging existing modern languages like Go, Swift, Kotlin, or Rust through message passing or APIs. Chandler explains Carbon’s unique approach to interoperability, which avoids the limitations of traditional abstraction boundaries.
[04:33] Chandler Carruth:
"These abstraction boundaries tend to need to be pretty robust... What about all the code we need to write that doesn't have that abstraction boundary... that's the code that's getting left behind."
He draws parallels with TypeScript’s superset model but highlights the constraints C imposes, which Carbon aims to overcome by maintaining low-level control and ensuring seamless interoperability without performance penalties.
A significant portion of the discussion delves into Carbon's novel compiler architecture. Unlike traditional compilers that rely on Abstract Syntax Trees (ASTs), Carbon employs a Semantic Intermediate Representation (IR) that retains detailed semantic information, facilitating advanced features like compile-time evaluation and metaprogramming.
[08:05] Chandler Carruth:
"From that very syntactical and structural parse tree, we generate what we call a semantic IR... It's something you could evaluate or lower into LLVM's IR."
This architecture not only enhances compile-time performance but also simplifies the lowering process to LLVM IR, thereby streamlining integration with C through Clang.
The conversation shifts to performance considerations when crossing interop boundaries between C and Carbon. Chandler elaborates on Carbon’s design to maintain a zero-copy memory model, ensuring that data passed between languages remains efficient without incurring runtime overheads.
[14:55] Chandler Carruth:
"We have basically the same memory model for all of the interop. We have to be able to realize kind of the identical ABI and memory layout on each side."
This meticulous handling ensures that interoperability does not compromise performance, a critical factor for high-performance applications reliant on C.
Chandler outlines the primary features Carbon introduces to modernize C:
Fast Compile Times: Carbon aims to drastically reduce compile times from minutes to milliseconds, enhancing developer productivity.
[21:00] Chandler Carruth:
"We shouldn't be measuring compile times in minutes or in seconds. We need to get down to that."
Generics: Unlike C’s cumbersome template system, Carbon introduces a definition-checked generics system that improves error messaging, reduces code bloat, and enhances type safety.
[22:15] Chandler Carruth:
"The very first thing, and probably the biggest single thing that we're adding in Carbon is this idea of definition-checked generics."
Memory Safety: Building upon Rust’s advancements, Carbon plans to incorporate memory safety without sacrificing performance, leveraging parametric type systems to enforce lifetimes and ownership.
[22:45] Chandler Carruth:
"Rust has really taught us what we needed... the information that kind of enforces correctness, enforces safety of lifetimes and ownership."
The discussion covers the practical aspects of migrating existing C codebases to Carbon. Chandler emphasizes an incremental and automated approach, allowing developers to translate C code to Carbon with minimal overhead and gradually adopt generics and memory safety features.
[27:31] Chandler Carruth:
"We want that to be kind of click button in the IDE, like as automated as conceivably possible."
This approach ensures that large, complex C projects can transition to Carbon without massive rewrites, facilitating broader adoption.
Chandler details Carbon’s governance model, designed to balance rapid development with community involvement. The structure comprises three leads to avoid bottlenecks and a unique "painter" role to resolve aesthetic decisions without hindering progress.
[41:56] Chandler Carruth:
"All the decisions we make are public... and then we can kind of consider that statement as leads and maybe make a decision that reflects it."
This transparent and flexible governance aims to foster community trust and ensure sustainable project growth.
Chandler candidly discusses the current state of Carbon, acknowledging that while significant progress has been made in toolchain development, full interoperability with C remains a work in progress. The upcoming year focuses on advancing interop capabilities and concretizing memory safety features.
[52:41] Chandler Carruth:
"This year our goals are twofold. One, we're going to try and get C Interop from kind of the nascent state... And then the second thing is, we've gotten feedback already that we really need to accelerate, kind of telling a concrete story about how memory safety fits into this picture."
The podcast addresses several criticisms from the community, particularly regarding syntax changes and the initial exclusion of memory safety features. Chandler explains the rationale behind syntax alterations, emphasizing compile-time performance benefits and alignment with modern language practices.
[55:15] Chandler Carruth:
"The first part is, I think, the cost... Syntax is relatively cheap now... we keep finding places where having the simplified syntax... actually helps make our compile times faster."
He acknowledges the challenges in balancing backward compatibility with innovation, advocating for iterative improvements based on community feedback.
The episode concludes with Chandler Carruth reiterating Carbon’s mission to modernize C by introducing essential safety and performance features while ensuring seamless interoperability. He underscores the importance of community involvement and transparent governance in achieving Carbon's long-term goals.
[61:58] Chandler Carruth:
"We have to make sure that that works. We still have to make sure we can add memory safety to this... it's a necessary goal for us to get to."
Key Takeaways:
For developers and organizations reliant on C who seek modern safety and performance enhancements without abandoning their existing codebases, Carbon presents a promising evolution in programming language design.