CppCast - Carbon, with Richard Smith
Episode Date: March 3, 2023Richard Smith joins Timur and Phil. After the usual news round-up, we chat with Richard about the new C++ successor language, Carbon. Richard is one of the three lead contributors to Carbon and he dis...cusses the philosophy and some of the special features that make Carbon different. News Conan 2.0 release CMake debugger in Visual Studio Unreal Engine - C++ Complete Guide The Italian C++ Conference Links P1881R0 - Epochs proposal P2137R0 - "Goals and priorities for C++" (from March 2020) Carbon GitHub org - with lots of links
Transcript
Discussion (0)
Episode 355 of CppCast with guest Richard Smith, recorded 27th of February 2023.
This episode is sponsored by JetBrains, smart IDEs to help with C++, and Sonar, the home of clean code. In this episode, we talk about the carbon programming language, one of the so-called
C++ successor languages announced last year.
We are joined today by Richard Smith.
Richard talks to us about what Carbon is all about, why it's great and where it's going.
Welcome to episode 355 of CppCast, the first podcast for C++ developers by C++ developers.
I'm your host, Timo Dummler, joined by my co-host, Phil Nash.
Phil, how are you doing today?
I'm all right, Timo.
I've been at home pretty much since we last spoke for a change,
which I have to say because after the last episode,
one of my colleagues said that he only knew that I was away on a holiday because of what he heard on the show.
So I need to keep him updated now. All right at the top of our episode I'd like to read a piece
of feedback. This time we have a piece of feedback from Spencer Common on Mastodon. Spencer is
disappointed that you said the beekeeper analogy generated a lot of interest and not a lot of buzz.
Yeah that analogy is the one that just keeps giving.
We did actually get another piece of feedback
from Mastodon, as it happens,
from JVAPen, I believe the username is.
And they said that they were glad to see us there,
but they did us some trouble finding us.
And it turns out that the address that we give
at Mastodon at cppcast.com,
well, we don't actually run a mastodon server but if the
mastodon client goes to that address it will find what's called a web finger file that's like a
redirect to our actual account it's just the way mastodon works we're actually hosted at cppcast
at hashiderm.io at the moment but we could change that at any time and that web finger would
redirect so that's the way we've set it up so if i type at mastodon at cppcast.com into a mastodon search
field, it will actually find our account straight away. That's how it's supposed to work. Apparently
it doesn't work that way for everyone. I don't know if it's a particular client or a particular
way you're doing it. So apologies to JVA Pen for making you work a bit harder and anybody else that's
had trouble finding us. So actually on the website, the Mastodon link there goes straight
to the Hashiderm account. So that can be the easiest way to find us if there's any doubt.
I will have a think about whether we need to change the way we say it on the show.
But I just wanted to clear that up just in case anybody else was wondering.
All right. Thanks, Phil. Speaking of which, we'd like to hear your thoughts about the show. And you can always reach out to us on
Twitter or Mastodon, as Phil just said. Or you can also email us at feedback at cppcast.com.
Joining us today is Richard Smith. Richard is a professional C++ language lawyer at Google
and one of the three leads of the Carbon Language Project. He has worked in great depth on the C++ core language, has authored over 100 C++ committee
papers, and was the editor for the C++17 and C++20 standards.
Until recently, he was the lead developer of the Clang compiler.
When not working on the guts of programming languages, he likes to play pool and to annoy
his cats by playing the piano.
Richard, welcome to the show!
Hi, it's great to be on the show.
I do like that phrase, professional language lawyer.
That does remind me, back when I was doing CPP chat with John Cowell, episode 28, one
of the very first episodes I did with him, was actually called Nobody Knows Enough Except
Richard Smith.
So you have got a bit of a reputation
to live up to but it also means that you've been in the title of a podcast but i believe you've
never actually been on a podcast so i'm glad that we finally got the scoop on you yes i generally
prefer to work more behind the scenes this is my first time uh on a podcast I've done one CppCon talk,
but that's pretty much it for talks and exposing my voice to the world, I suppose.
Yeah, well, we're very honored that you're here today.
So thanks for that.
All right, we'll get more into Richard and Carbon
in a few minutes,
but we do have a couple of news articles to talk about.
So Richard, feel free to comment on any of these
if you like, okay?
So the first one is
Conan, the open source C++
package manager, actually has released version
2.0 last week.
And so apparently Conan has
been re-architected from the ground up,
has lots of new features, there's
completely new written documentation
written from scratch, there's a new command line
interface, there's a new public line interface. There's a new public Python API.
There's a new configuration system.
There's custom commands.
There's much, much more.
They have a blog post where they explain all this.
It's a very, very impressive list of new features.
So that's very interesting.
Yeah, this is really big news, actually.
Conan's history goes back a long way.
Even before there was a Conan,
Conan itself is a successor language. of successor languages but before that there was a b code most of the
same people that worked on that although it's a separate project and i first heard about that
from one of the very first episodes of cpp cast as it happens so our histories are intertwined
so yeah it's great to see this having such a big overhaul for version 2,
showing that it's really maturing now, I think.
And the one bit that stood out for me was the public hyphen API.
I think that's really going to open up a lot of possibilities.
Yes, and I think Conan is also filling a really important role for C++,
that the absence of a package manager has really been
a problem and it's
great to see investment in this space.
Absolutely.
We have more tooling news.
Actually, there's a new preview of Visual Studio
which now has a CMake debugger.
This is something
that we at JetBrains have added in CLine
already last year, but it's very nice to see that
other IDEs are catching up.
I thought it did sound familiar.
Yes, yes.
So they do have a blog post about it.
So there are some limitations,
like it only works the version of CMake
that's bundled with the IDE.
It doesn't work with WSL.
It doesn't work with remote machines.
So those are pretty much the same limitations, actually,
as we have in CLion.
So that's really interesting.
Yeah.
From what I could tell about looking at it quickly,
there's like one difference with the CMake debugger
in Visual Studio.
If you want to look at the values of your CMake variables,
it's like down in the locals window,
whereas in CLine, you can see them directly
in the editor window.
But other than that, it looks like it's
a pretty similar feature set.
So I haven't actually had a lot of time to really hands-on
try out the Visual Studio version, but I'm going to do that.
So it's definitely good to see that more and more IDEs
have these CMake debuggers and other tools like that.
I mean, I hope you don't have such complicated CMake
that you ever need a CMake debugger.
But I guess if you do,
then it can be quite life-saving
and it's great that now
multiple IDEs are offering them.
I think if anything,
it just shows that Microsoft
are taking the CMake integration seriously.
So a few years ago,
since I last looked at it,
it was early days at the time,
but it was a bit bolted on at the time.
So hoping that's a bit progressed since then what
i've seen is cmake rules is they they seem to tend to grow until they're at the limits of the
understanding of the people who maintain them so i think eventually everyone needs a cmake debugger
sadly i think that's true okay and then we have one more um new blog post which is not about
tooling per se and not a topic that i think we talk about very often on this podcast,
but the blog post is called Unreal Engine C++ Complete Guide.
And it's a really, really long article going over lots of unique aspects
and quirks of how C++ is used in the Unreal Engine.
And I was reading that, and I was really fascinated by it.
This is obviously, I think, gold for someone who's getting into Unreal Engine development
and kind of starting out with that world.
But for people who just don't use Unreal Engine at all,
like myself, for example,
it's super fascinating insight into how things are done there
and how do you do things in that world.
So I just had a quick look at it.
And for example, in the Unreal Engine,
they have interfaces,
which we don't really have in plain C++.
And they're all implemented with macro magic.
So I found that really interesting.
They don't use the built-in C++ casts,
like static casts, dynamic casts,
instead they have their own cast function template,
which has different semantics.
And there's like a lot more stuff like this.
So they do think things differently,
but it's a highly popular ecosystem so
um and it's yeah it's a very thorough kind of article about how this all works so i thought
that was super interesting for anybody who's curious about unreal engine and how c++ is used
there as a language and how it kind of interacts with the that ecosystem i'd be interested in seeing
a deep dive into how some of the macro magic works, because
it seems like they've got some very interesting things going on there.
Yeah, yeah.
So what from what I saw, you have like a macro all capitals interface, you give it a class
name and then you have a you define something that looks like a C++ class, but with more
macros inside and then the compiler does something with that.
So I haven't had the time to dive deep into that,
but it seems like it's very useful for them.
So I'm curious how that works.
We're also going to talk about interfaces
a little bit more later with you, Richard.
Before we get to that.
Nice setup there.
Yeah.
Before we get to that.
Foreshadowing.
The last news item for today
is about a C++ conference.
And I know we had a lot of C++ conference news lately.
We're kind of over the big influx of conference news for now,
but we do have this one more announcement,
which is the Italian C++ conference.
It's happening again this year.
It's a one-day in-person conference
taking place on the 10th of June in Rome, in Italy.
And it's free to attend.
I thought that was remarkable because that's not usually the case for C++ conferences.
And their call for papers is open until 2nd of April.
So it's about a month left to submit your talk there.
And you can do that at italiancpp.github.io slash con23.
I went there one year.
It's a great conference.
And because it's free, if you're not too far away,
obviously you have to cover your travel,
I think it's worth attending.
Amazing.
So speaking of conferences,
one thing that happened at conferences last year
was that we had not one, not two,
but three new programming languages announced
at different C++ conferences last year.
And they were labeled by some people
to be so-called C++ successor languages, quote unquote.
It's a really hot topic at the moment,
so we decided to do a series of episodes
on these so-called successor languages.
And we started last month with Val,
and we had an episode with Demira Cordon,
who told us that Val isn't
really a C++ successor language, as far as she's concerned.
It's a really cool programming language that solves a bunch of problems that C++ has in
very interesting and elegant ways, but it's not so much designed to be a successor in
the sense of having good interoperability with C++.
So that's not one of the primary design goals of Val.
So today we're going to move on to Carbon,
which actually explicitly calls itself a C++ successor language.
So that's definitely a bit different.
It is an experimental programming language started by Google
and first announced by Chandler Carruth at CPP North last year.
And we thought about whom to invite for this episode.
And Carbon currently has three lead developers.
So that's Chandler himself, that's Kate Gregory,
and that's Richard Smith.
And we wanted to invite Richard on the show
because Richard is awesome and Richard is doing awesome work.
And also because Chandler and Kate have been on the show already
in the past and Richard hasn't yet.
So it seemed like the perfect opportunity.
So thank you so much again
Richard for joining us here today thanks for having me on the show and yeah so we're here to
talk to you about carbon and actually uh what we thought is that we're going to ask you very
similar questions to the ones we asked Dimi about Val and let's see how that goes so I guess I guess
my first question is so what is carbon about and how did you get involved in carbon I guess my first question is, so what is Carbon about and how did you get involved in Carbon?
I guess that's two questions.
So like the elevator pitch.
Okay, so I think in order to understand where Carbon is, I think you need to think about where C++ is.
C++ is a very broad language that tries to be everything to everyone. And due to having this focus on source-level backwards compatibility, it's been accumulating features over the years.
It's, I think, got a reputation that is deserved for being a very complex language with just a lot of things being added.
And ideally, those additions work really nicely together.
And we do a lot of work in the C++ committee to make sure they do.
But I think you can't keep scaling a language like C++ up in that way
without there being times when features don't work so well
with especially very old features, features that are still there from C,
features that were added in the C++ 98 days
and haven't really
grown with the language. And in late 2019 or so, some of us made the observation that that's not
only leading to a language that's growing in complexity over time, but also leaving some
performance opportunities on the table and leaving some safety on the table where
maybe there are different ways we could do things now which would be inherently safer or would push
people towards safer options. And so a group of us, including people from Google, people doing
big data things, people doing HPC, some people in finance, wrote a WG21 paper.
This was P2137 that was proposing a set of prioritized goals for C++ to say where we would like to see C++ go,
which things we'd like to see prioritized over other things
so that there's less of an effect of the hundreds of people
in the C++ committee pulling it in all sorts of different directions and those directions sometimes conflicting with each other.
And so in particular, we wanted to see a prioritization of performance.
We wanted to see a shift away from this really strong focus on source level backwards compatibility
into a focus more on evolution, both of the language and of libraries
written in that language. And we wanted to see a focus on ergonomics and safety to an extent that
C++ didn't entirely have at the time. And this was discussed in the committee, and it seemed like the
committee was interested in some of those ideas but didn't want to commit to a particular set of goals.
And so we thought, well, if the C++ committee and the C++ language isn't going to quite go in the direction we want, then maybe we should be experimenting with this ourselves.
So we thought, what would it look like for us to fully commit to this direction, to this set of prioritized goals?
And Carbon is an experiment to build a language
that satisfies those goals that we had for C++.
Plus an additional goal, because Carbon is a new language,
to interoperate with your existing C++ code
in a way that's as smooth as we can make it
and to also support a fairly transparent migration
of C++ code to Carbon.
So it's a new language,
so you will need to support your code
from one language to the other,
but we want that to be as close
to like a push-button conversion as we can make it.
And I think Carbon also gives us
a really great opportunity to rethink
a lot of the ideas of C++,
to go through everything,
go through every design decision and think,
is this what we want in a new language
is this something that we can reasonably change and still satisfy those migration and
interoperability goals or is this something where c++ actually got it right and we should just do
what c++ did because it's great those all sound like great goals but i know what some people are
thinking you mentioned um lots of people at Google,
Google engineers in general.
Is this just a Google thing
or are there other people involved in it as well?
Carbon's an open source project.
It's intentionally not trying to be a Google project.
You mentioned our three leads, Chandler, Kate, and myself.
Kate is not a Googler.
We do have some Googlers contributing to Carbon.
But at the moment, we have a bunch of other people as well.
Like in the last quarter of last year,
we had 14 people actively writing patches of whom only five are Googlers.
So we're about two to one non-Googler to Googler
in terms of people who are contributing,
at least by number of people.
By volume, it's a little bit less non-Googler than that.
We had, I think, 250 plus people filing or responding to issues last year and currently
have about 200 weekly Discord users.
And almost all of those are not Googlers.
And we have contributors from all over the world,
and we have a really strong focus in the project on our community, on conduct, on moderation.
We want to ensure that we have a really diverse group of people
and that they feel welcome there,
and that we are open to everyone,
regardless of whether you come from a corporate background
or whether you're a hobbyist.
If you want to contribute to Carbon, we want you to contribute.
Okay, so I don't know if you've been following much the evolution
of the other two successor languages that were announced last year,
Val and CPP2 slash cpp front that's
herb's project do you have any opinion on you know how carbon is different uh from them or special
or like tries to do something else so carbon has an ongoing goal to uh to make the language
evolvable as well as code written in it we don't want Carbon to stop changing as the state of the art improves.
And I think maybe in the longer term,
that might be something that sets Carbon apart,
that its commitment to that,
rather than accretion of features over time,
will enable it to stay well-suited to its audience for longer.
But I think among all these successful languages,
all the C++-adjacent languages we're seeing now,
which is VALCGP2 and also things like Circle,
they're all taking a lot of inspiration from each other.
And I think we're going to see a lot of conversions of ideas over time.
So you're talking about the evolution of the language.
One of the problems with C++ is that backwards compatibility, as you said.
And there was an attempt just before the pandemic, actually, beginning of 2020,
to introduce something called Epochs into the language based on Rust.
What's the term in Rust?
Anyway, the Rust thing.
And it didn't go anywhere, although there's a lot of interest in it
just getting compatibility between different versions of c++ seemed to be hard enough
there was like interplay between templates between different epochs that cause issues
so um and how do you plan to overcome those sort of difficulties but both between different
versions of carbon but also between carbon and C++ without interoperability.
Yeah, there's a real combinatorial problem there
that because different languages and different versions of languages
think about the world in different ways,
you really do need to think about how you're going to bridge
between any two given languages,
whether it's you and an older version of you
or you and someone else.
In Carbon, our goal is to avoid having a system
that's like Epochs and instead to the extent that we can
to get the code using the language
to evolve with the language.
So part of that will be making it easy and low cost for people to upgrade their
code as the language changes and to really encourage people to do that. And part of that
would be having tools where we can to help people out with that process. But fundamentally,
the way I look at it is your language should be thought of as a dependency in the same way that your libraries are.
And you don't want to stay on an old version
of a library that you're using,
even if the API changes a bit as you move to a new version.
And you don't want to stay on an old version
of the language either.
So rather than saying we're going to have
two different versions of this library dependency
in our project, which we know leads to all sorts of messes,
we don't want to have two different versions of the language either.
Right, that's interesting.
So I know that in C++, at least for some industries,
it's a huge problem if the language itself changes.
I can think of two things.
For example, in safety-relevant applications,
you have certification where you certify a code like a header file that's used by different components of a car or elevator or
whatever. And then you can't really change it afterwards unless you want to spend like hundreds
of thousands of dollars on getting it certified again. And the other cases where it's important
to keep ABI compatibility, like for example, I used to work in the audio industry where
we had this case of, there are several companies that are making their money with selling super cool sounding DSP algorithms, but they don't want to give you their code because that's where the IP is.
So they just give you a precompiled binary and a header.
And then I actually experienced this case where you're sitting there with a header and a binary, and then then Visual Studio upgrades from 2008 to 2010 and the ABI changes.
And you want to recompile the new compiler and you have to bug the person at that company.
Can you please recompile everything for us and debug and release?
And sometimes if it's like a one-man company, then it's like, oh, sorry, I'm on vacation.
And so that's why you know abi compatibility is
really important at least for some people so it sounds like carbon is taking like a very different
take on all this and like it kind of assumes that you can just a kind of recompile so a change your
code at any time and use like certain automated tools for that. And then B, you can recompile your whole code.
That's kind of assumed.
Did I get that right?
So we see two worlds here.
For the first part of your question about the domains
where you would have to recertify if there's a new language
or you can't keep up to date with the trunk language.
For those situations,
we're thinking about having LTS releases of the language,
probably with a very slow cadence.
We've talked about maybe every 10 years
cutting an LTS release.
And yeah, that will create the kinds of compatibility problems
that you would get between two versions of a language,
between epochs, between any two systems
that you want to interoperate.
And those, I think, fundamentally are a challenge.
And we don't have a magic wand
to make that challenge go away, I'm afraid.
But by making those infrequent
and allowing us to really focus on keeping those stable and robust, we think we can deliver something that's useful there for the people who, for whatever reason, can't or don't want to keep up with an evolving language.
On the ABI side, we don't want Carbon to inherently have an ABI that's applied to
all Carbon source code. If you're
building a project
that's like 80%
built from your own source code,
there are overheads to having
hard ABI rules that
we can't look through. There are performance implications of that.
And there are lots of constraints on how
the language can change if you have an ABI
boundary that's like that.
So our intent is to not have a hard ABI surface within that code.
But when that code's interoperating with a library that someone else is vending you that wants to have some source-level way of annotating, like, this package has hard ABI requirements and expectations and won't change over time.
We want to be able to write down what the ABI rules you'll get for that kind of the approaches to source level compatibility was that there
would be breaking changes regularly but there will be tools that would help you to migrate the code
forward so is that still the goal that's that's still an idea um that's that's still part of the
plan we don't know to what extent uh we'll want to do that with tooling versus some other solution.
At some point, we had the idea that every change to the language would always come with
a tool.
And we may be moving away from that a bit, but it's still very early.
We're still experimenting to find out what's going to work best for people.
Yeah, that's interesting because I watched the introduction of Swift right from the first days,
and they had the same statement at the start that at least for the next few years,
it's going to change rapidly and it's going to break code,
but there will be tools that will migrate your code forwards.
And sometimes they even worked.
They weren't 100%, so there were a lot of people complaining about it,
even though they were the early adopters.
So it is something that I've been a bit sceptical of,
but I think it's part of an overall strategy that they have their place.
I certainly think what we're expecting to see is that the rate of big breaking changes
will go down as the language matures. And also, the amount of usage of the language will
ideally go up as the language matures. So the need for tools due to language changes is sort of
inversely correlated with the need for tools in terms of usage. So maybe the sweet spot is somewhere else.
Well, talking of pitfalls and headaches,
if you hold that thought,
because we do have a word from our sponsors just to bridge us to the second half.
So this episode is supported by JetBrains.
JetBrains has a range of C++ IDEs
to help you avoid the typical pitfalls and headaches
that are often associated with coding in C++. So exclusively for CppCast, JetBrains is offering a 25% discount for purchasing or
renewing a yearly individual license on the C++ tool of your choice. So that's one of C-Lion,
ReSharper and ReSharper C++ or Rider. Use the coupon code JETBRAINS for CppCast
during checkout at www.jetbrains.com.
And back to the show.
All right. Thank you, Phil.
So one other hot topic,
apart from successor languages,
lately in the C++ community, is safety.
So, and whatever that means,
like it's a big topic,
but I want to talk a little bit about
that because i think it's it's kind of a relevant part of the puzzle puzzle here so from what i can
tell there's a bunch of different types of safety there's like you know systemic safety
and on the language level there's like type safety memory safety threat safety
arithmetic safety things like ub on overflow and memory safety itself you safety, arithmetic safety, things like UBE on overflow,
and memory safety itself.
There's bounce safety, lifetime safety, initialization safety, object access safety.
So what's your take on this?
Which of these does Carbon solve or aim to solve, and how?
And which did you choose not to solve at this time?
This is a really interesting topic, and it's one that's become increasingly important over
even the past few years.
I think in the three years since we started really working on carbon, it's gone from being
something that people consider to be important to something people consider to be critical.
I think part of that is due to pressure from the US government. And I think in WG21 as well, in the C++ committee, this is something that people have started really pushing on.
Safety is something we always planned to be part of the 1.0 release of carbon.
But because of the increasing importance, it may end up being something that we push more into an earlier
stage, into maybe the 0.2 release. The design for safety in Carbon is quite incomplete at this stage
and we'd definitely be interested in hearing feedback from people on what features they want,
which things they think are less important. An important part of our safety strategy is to allow people to specify what kind
of code they're building, because not everyone needs the same kind of safety behavior from their
code. And we in particular want to distinguish as build modes a performance build from a hardened
build. And we also have a debug build mode for development.
But the key thing is for a hardened build,
we don't want for there to be any unbounded,
undefined behavior where security vulnerabilities
that you didn't write yourself in your code are introduced.
Whereas in a performance build,
there may be some cases where
there's such a strong trade-off between performance and the potential for some bad thing to happen,
that if you really care about getting every last cycle of performance out of your code,
then it's worth making a trade-off. But overall, because we're still in an early stage, we want to run lots of experiments
to figure out exactly what we want to do and what's going to work well for us. But the goal
is for it to be reasonable to write memory-safe code in Carbon. And that's kind of fundamentally
bounded, though, because Carbon also wants to have really good
interoperability with c++ and we can't make existing c++ code memory safe we want to be
able to support smooth migration from c++ and that migrated code has fundamentally got to land
in a space where either you're paying some overhead for doing additional checks that the
c++ code wasn't doing which wouldn't really be in line with our goals,
or it has the same kinds of issues or potential for issues that the C++ code had.
So there are limits there.
And part of the strategy is to allow the features that we provide for safety to be adopted incrementally. Okay.
So one thing that I found quite remarkable about Valve,
when we talked about it last month with Dimi,
was that they have kind of similar to SafeRust,
they have this programming model where memory safety is kind of guaranteed by design.
And Valve does it through mutable value semantics
and Rust does it through BorrowChecker.
And so do I understand it right
that you don't have anything like this
because you rather kind of,
the trade-off is that if you have this,
you can't really have good compatibility with C++,
which neither Val nor Rust have.
And instead you want to like have the compatibility first
and then kind of incrementally get to a place
where you can reason about the safety if you're caught better than in C++ and have overall more safety
than in C++, which isn't this kind of complete safety by design,
by kind of restricting what you can do with the language,
the way Val or Russ do it.
So we want people to be able to incrementally reach a world
where they do have complete safety by design but the the way
they get there is expected to be by incrementally adding annotations and by eventually turning on
some kind of safe mode for uh for your library for your package that says i think i've done i
think i've done everything give me an error if i haven't. But there's a question of what the defaults should be.
And that's still something we're working out.
Something that we seem to be very settled on at the moment
is a much greater emphasis on pass-by-value and value semantics
than in C++, moving somewhat towards the Val model,
but perhaps not all the way to the Val mutable value passing.
I think what Val is doing in that space is very interesting,
and I think we can take a lot of inspiration from that.
Another thing that we're considering,
and I think we're fairly settled on, is an idea of saying when you pass a pointer into a function, that by default, we assume that that function won't store a copy of that pointer.
It won't capture it.
And we can do quite a lot of enforcement of that in the carbon type system.
And again, this is one of these things that's going to be limited by C++ code.
The moment you call into a C++ function, you lose that guarantee. But that gives us a fair amount
of lifetime safety. And then maybe on top of that, we might add something like Rust lifetime
annotations, but it's too early in the design stages at the moment to say.
That's interesting. So if I may observe something. So what you just said about
achieving fault safety incrementally by adding annotations and additional rules and things like that.
It kind of reminds me a lot of Bjarne's paper, P2739, where he proposes to do exactly that with C++.
So it sounds like it might actually be a viable approach, even though I guess for a new language, it's quite a lot easier than for C++. So it sounds like it might actually be a viable approach, even though I guess
for a new language it's quite a lot easier than for C++. But it seems like that's a viable
direction potentially.
Yes, we hope so. There's still lots of experimenting to do to find out if that pans
out in practice. And if it doesn't, then we may need to look at other strategies do you have a um
a default philosophy i suppose towards undefined behavior
you're just completely adopting the c++ model or is it more of an opt-in approach
for the hardened builds in carbon we we don't want to have unbounded undefined behavior we
want to put hard limits on that so for example for uh arithmetic
overflow after lots of thinking about exactly what the the right semantics are and what's the
best thing for performance versus versus safety we ended up with a model that's somewhat like
c++ but also somewhat like rust so in the in the hardened build, we will give you a definitive value for arithmetic overflow, and it might be zero, it might be two's complement.
It's not guaranteed, but it's going to be something that's not undefined.
Whereas in the performance build mode, it's less clear.
We're still experimenting there to decide, from a performance standpoint, can we we reasonably say oh it's it's always defined but you just get back some
some unspecified value if you overflow or do we get sufficient performance advantage
from overflow being undefined that it's actually worth doing that in the performance build mode
but we want to expose to the programmer that choice of whether they're in a security
sensitive domain whether they're in a case where it actually really matters that that you don't get
junk back in that case and maybe even the the hardened build mode if it can be done with a
relatively low cost should trap on those cases so performance is clearly a priority. So what's the performance going to be
like? Should it be as good as C++ or better or some overhead? We are aiming for it to be as good
as C++ in every case and better in at least some cases. We think we can do better than C++ in at least some areas.
And ultimately, if there's some efficient way of representing an algorithm in LLVM,
we want you to be able to write carbon code that gives you that expression in LLVM.
So whatever code you're building, if it can be fast,
you should be able to write it in carbon and have it be fast.
Do you have any examples of something you able to write it in carbon and have it be fast do you have any examples of
something you can make perform better in carbon than the equivalent in c++ just curious sure um
so in c++ when you want to pass an object by value to a function uh you have two choices you
can pass it actually by value or you can pass it by const reference. And if you pass it actually by value, then the compiler can look at that and say, I see there's no other
references to this thing. It's a brand new name. It's a brand new object. So I can assume that
some other store that happens in this function can't change the value of that. Whereas if you
pass it by const reference, you don't have that assumption. You can't say that a value that comes in from
your caller can't possibly alias something that you assigned to in the body. And generally,
you're making the choice of whether you pass by value or pass by const reference,
not based on whether you want to refer to some existing object with a longer lifetime,
but rather based on whether you think you can afford to make the copy.
So in Carbon, we're looking at unifying pass-by-value
and pass-by-const reference
so that you as a programmer don't need to make that call.
You don't need to decide,
is this big enough that I actually want to pass it by const reference
or actually do I want to allow it to be passed in a register?
The language will figure that out for you.
And you still get the benefit that in the body of the function,
the compiler can assume it has a unique copy. That sounds very similar to Val's model. that out for you and you still get the benefit that in the body of the function the uh the
compiler can assume it has a unique copy that sounds very similar to to l's model
yes in many ways it is interesting yeah that is really interesting i want to get back to something
we discussed earlier when we were talking about backwards compatibility so you were talking about
basically backwards compatibility with like previous versions of Carbon and how you would upgrade to a new version of Carbon.
But what's the story with compatibility with C++?
So I know that, you know, full compatibility with C++ is kind of one of the design goals, one of the requirements.
But I wonder what this practically looks like.
So, for example, last time i looked i
think carbon didn't have overloaded functions as fast does so you know what's the kind of idea
what's this what's the story about how you would kind of interoperate with c++ code that has
certain features that carbon doesn't or that carbon does differently like how would you how
would you do that so overloaded functions are on our roadmap.
They're coming, but they're going to be limited
compared to C++.
So we intend for an overload set to be something
that you think about, you design, you implement
all at once in a single place
rather than having it be distributed
across your entire program potentially.
So when you're writing your overload set,
you can say, I want to pick this one if I can,
and then that one if I can't, and so on,
and not have to deal with the myriad ordering problems
and deduction overload selection problems
that you get in C++ because of open overloading.
But as you say, we need to interoperate
with open overloading in C++,
in particular with argument-dependent lookup.
So the way we're thinking about addressing this is to use Carbon's generics system to reflect C++ argument'd have an overload set distributed across many namespaces that would get mapped into, on the Carbon side, a special interface that represents that ADL set.
And if you want to extend it from Carbon, you implement the interface, and C++ code that tries to use ADL will also look in the Carbon interface for that name. And if you want to call the ADL overload set in C++ from Carbon,
you would call the member of that interface to look up the relevant function from the C++ world.
So that's actually funny.
Like when I hear you talk like this, I just notice again how horrendously complicated C++ actually is.
Like when you talk about overload resolution and ADL,
like that's already
like, I don't know,
you need like 10
years at least to
figure out how this
works in C++, right?
Yeah, I was thinking
about just one over
half of our audience
talking about
overloading.
So you mentioned
generics there.
I seem to remember
that you've got some
differences in the
way you do generics as well.
It's not just all about templates. What can you tell us about that?
Yeah, so for Carbon's generic system, we have type constraints that are a little bit like C++20 concepts
in that you don't just say, oh, I want a type parameter. You can say, I want this kind of type parameter.
But interfaces in Carbon are nominal rather than structural,
by which I mean you don't satisfy an interface
just by having the right member functions.
You need to explicitly say,
I actually meant to satisfy this interface.
And the names on your type that implement those things need not be members.
You can divorce the implementation of the interface from the members of your type.
So for instance, if you implement a comparable interface and you have a function compare,
you don't have to have a member function called compare.
That can just be part of the way you implement that interface unlike c++ 20 concepts c++ 20 concepts are basically predicates over types yeah whereas
interfaces uh in carbon are much more like rust traits so they are declared and they're structural
and they form a type in the type system so So one of the benefits of the Carbon Generic system
is that we can perform separate checking of generics
without seeing which actual type you're using them with.
So unlike templates, we can check the body of a generic
against the definition of an interface and say,
you used function foo that's part of this interface, that's okay, we know what type it returns. You used
function bar that's not part of this interface, that's an error. But Carbon also supports
C++-like templates that are checked by substitution as a mechanism of interoperating with and
migrating from C++ code. This is something that we think is going to be necessary.
And we've designed a system where you can smoothly migrate
from a template to a generic by incrementally adding constraints.
And then when you don't need the template facilities anymore,
when you're purely using the declared interface of the type,
you can switch over and Remove the template support.
That's really interesting.
It sounds like actually Carbon generics
are more similar to C++ or X concepts
than there are to C++ 20 concepts.
Like the older version of this
that got yanked from C++ 11,
but also not quite
because I don't think C++ or X,
like that initial design
had this thing
that you're talking about where it doesn't matter
if you implement something as a member function
or as a non-member function.
It was kind of like,
if you want to be adhering to this interface,
here's what you need to implement.
Whereas kind of your system is a bit more clever than that.
Yeah, so it's pretty similar
to C++ or X concepts in that regard.
There was a feature at some point
in C++ or X concepts called concept maps. There was a feature at some point in C++ OX concepts
called concept maps, which is in a very similar space.
Okay, yeah, I'm not familiar with that.
I'm going to familiarize myself with that
or maybe just go straight in and familiarize myself
with carbon generics because it's actually quite fascinating.
Actually, I had one more question,
which is kind of a bit different
and it's more about compatibility with
platforms so
obviously you know
C++ has multiple
major implementations it works on
all desktop operating systems it works
on mobile operating systems it works
on embedded
what do you envision for Carbon
should it be should run on like all the platforms that
c++ can currently run on is it dependent on llvm like will it work on windows will it work on
iphones will it work on like my little embedded microcontroller like do you have any ideas where
this is going to go so our goal is for Carbon to support every modern platform that it
reasonably can. We're not so much interested in supporting the full breadth that C++ can support.
For instance, systems where a byte is not eight bits or where you don't have any access to IEEE
floating point are not something that we want to be supported as smoothly as
modern systems where a byte is 8 bits. We think it's important to support 32 and 64-bit platforms,
but maybe not 8-bit microcontrollers. It's not really the domain we're looking for.
You mentioned Windows support. That's definitely something that we want to have. At the moment,
we don't really have very much in the direction of Windows support talked a lot about the concepts,
not concepts, concepts,
but the concepts behind the language.
It's very difficult to talk about syntax
on an audio-only show,
but what about things like,
you mentioned the defaults,
getting the defaults right.
Have you taken the opportunity
to fix some of the defaults
where C++ got it wrong
or they became wrong over time?
Yes, this is something that we've tried to take a holistic look at.
Syntax in particular is an area that we've been thinking a lot about.
So the C++ syntax is notoriously hard to parse,
and we want Carbon to be something that's a lot simpler
for someone to write their own parser for.
So we're taking an
approach there of looking very hard at our grammar rules and making sure they are consistent and
orthogonal, using introducer keywords wherever they make sense to disambiguate the grammar and
to avoid the situations in C++ where you're not sure whether something's a statement or a declaration,
start of an expression. And we really want it to be clear both for tools
and for the human reader what the meaning
of any given carbon statement is.
Less vexing.
Less vexing, yes.
Is it going to be context-free grammar then?
Ideally, LR1.
Another place where this shows up is in carbon's operators.
So in C++, and in a lot of languages, there's a strict hierarchy of operator precedence.
We just have a table of saying this one is high precedence, then that one is high precedence, then that one.
And in a lot of cases, there is no obvious good answer.
Like, what should the relative precedence of bitwise
and and plus be? It seems very unclear a priori which of those you should prefer if you see
an expression that involves both and has no parentheses. And C++ has actually ended up in this
really unfortunate position there, where the bitwise operators and the logical and and or
have nearly the same precedence for historical reasons from the new B era before new B was even
called C where there was only one operator for logical and and for bitwise and it was spelled
the same way and sometimes it short-circuited and sometimes it didn't. And it was decided that these should be separate. But in order to minimize the disruption
on the existing half-dozen new B programs, they kept very similar precedents for those two operators.
And so in modern C++20 and C++23, these two operators have very similar precedents today.
That's just a wild consequence of decades and decades of source compatibility, rather than ever taking the opportunity to start again and build a new language.
So in Carbon, what we said was, we're going to look at operator precedents, look at the two operators, and if there is a reasonable
simple rule that we
expect every developer to be able to
remember, like star
binds tighter than plus,
then if there's a simple rule, that's
the rule you get. If there's not a simple rule,
then you need parentheses,
and the grammar requires you to have parentheses.
And we think that's going to make
programs a lot more readable
than having a table.
Yeah, that does sound very worthwhile.
Although when we were talking about defaults,
I was thinking more of things like,
are things const by default, noexcept by default,
maybe even constexpr by default?
Is there an opinion on those?
So for const by default, where we've ended up is, I guess more generally,
if you have a choice of A by default or B by default,
and A is going to be right for some people and B is going to be right for other people,
and there are contexts where you almost always want one or you almost always want the other one,
then any default is going to be a little bit unsatisfying.
So where we ended up for const is there isn't a default.
You either say let if you want a constant,
or you say var if you want a mutable variable.
For a lot of other things,
we have tried to pick defaults that we think are the most appropriate that they can be,
thinking about readability as well as writeability. So,
for example, in a class, we felt that there are readability issues with having access labels.
It can be very hard in C++ to see a class, see a function in it, and know,
what's the access of that? Can I call that? Maybe I need to scroll up a couple of screens worth of
text to find the nearest access label, and maybe I missed one when i was scrolling kind of awkward but if you make access labels be mandatory in every declaration then
you're going to add a fair amount of syntactic overhead so we ended up on java right yes like
java so where we ended up is by saying that in a class the the most important thing the most
important user of a class is the user of the class,
the person who's reading it and they want to call methods on it. And so the most important thing for
them is that the method declarations in text is easy to read. So public is the default,
because the public interface is the one that the reader of the class cares the most about,
and we want that to be most readable. And that's kind of a similar philosophy to that,
has informed a lot of our defaults.
Okay.
Well, that's very cool.
I do have another question, which is,
what's next for Carbon?
Like, do you have a roadmap?
Do you have any idea when you release like version 1.0?
Or when you're going to be able to like recommend Carbon
for new projects or when it's going to be complete enough
for, you know, actually developing something like an app? recommend Carbon for new projects or when it's going to be complete enough for
actually developing something like an app.
Actually,
I saw it's on Godbolt now,
but also the docs
on GitHub say that currently there is no working compiler
or toolchain. So do you have
any idea when that's going to be available?
Okay, so we do have
a roadmap. We
mostly plan with a one-year time horizon for our roadmap and
the current roadmap for 2023 is is on github uh that's github.com slash carbon hyphen language
and there's all sorts of information there about how to join the project get involved as well as
the roadmap our goals our plans the current design that kind of thing
in terms of reaching 1.0 release,
we don't have a concrete date for that.
We're currently working on what we're calling our 0.1,
which is kind of our minimal viable product
for experimentally testing to see,
is this language that is going to make sense?
We want to try that in some actual problem domains
and see if the interrupt works, if it gives the kinds of benefits that we want it to before we finish building out the entire thing.
And so that's our 0.1.
And our goal is for 0.1 to be completely design complete and have a solid implementation by the end of next year.
But this may slip.
It's not a promissory guarantee.
So design complete for a real-world experimentation next year.
This year, we want to be roughly complete with the 0.1 design
and to have an initial implementation of the rough design
in what we call Carbon Explorer,
which is kind of an interpreter for Carbon that's designed to be
hackable and to give output that allows people to understand what's going on with their program.
It's not a compiler per se. And that's the thing that runs in Matt Goldbald's Compiler Explorer
right now. We also want by the end of this year to have a tool chain that's sufficiently complete
that we can build real programs with just a little bit of interrupt
with C++ going on.
So this will be enough
to use the C++ type in Carbon
and to call a C++ function from Carbon,
but maybe not so much interrupt
in the other direction yet.
That's kind of our short-term plans there.
So if anybody who's not a member of your team
wants to play around with Carbon right now,
the only thing they can do is to go on Compiler Explorer?
They can go on Compiler Explorer.
They can enable the Carbon language there and start writing code.
And that will be able to interpret and run your program.
You can check out the Carbon project from GitHub
and you can build your own Carbon Explorer
and run programs through it that way.
You can check out the toolchain and build that, but at the moment it's not quite able to generate code yet. We're very nearly at the point where we're going to start
generating code, but not quite there yet. So for the time being, the Carbon Explorer
and Carbon Explorer in Compiler Explorer is probably the easiest way to go.
But the language is still very much an experiment at this point.
And there's still a lot of gaps for serious usage.
So it's definitely not ready for people running off and rewriting important systems in Carbon just yet.
Right.
We are running out of time,
and we spent the whole episode talking purely about carbon
we didn't really get to talk about you richard so just have one more question for you
which is are you still involved in the c++ community at all yes i'm still uh a little bit
interacting with the c++ committee i have uh i don't have as much time for that as i used to i
don't have much as much time for kind things as I used to,
but I am still a little involved in both.
And within Google, there's always C++ puzzles that come up
that are fun to work on.
Just last week, we had an issue with some internal system
that wants to take a variadic pack of types
and deduplicate it as quickly as possible.
So I was looking at a better way of doing that.
Actually,
here's a wrong,
uh,
some,
an interesting approach for this.
It's good to hear you haven't abandoned us yet.
I think it's fair to say that you no longer know everything about C++.
So we've come full circle.
No pun intended.
So,
uh, anything else you want to tell us before we
before we let you go i think that's it thank you for having me on the show it's been fantastic
no thank you for honoring us with your with your presence it's been a while
okay um do you want to tell people perhaps where they can reach you if they have questions about carbon
or kind of the stuff that you do oh yes absolutely uh if if someone wants to reach out probably the
best place is to join the the carbon discord so if if you go to our github project github.com
slash carbon hyphen language there's all sorts of links there as to how to get involved and join and a link to our
Discord. And on Discord, I am Cygoloid. All right. Thank you so much for listening in as we chat
about C++. We'd love to hear what you think of the podcast. Please let us know if you're discussing
the stuff you're interested in. Or if you have a suggestion for a topic, we'd love to hear about
that too. You can email all your thoughts to feedback at cppcast.com. We'd also appreciate it if you can follow CBPCast on Twitter or Mastodon.
You can also follow me at timur underscore audio on Twitter and at timur underscore audio at
hackydam.io on Mastodon and Phil at phil underscore nash on Twitter or at mastodon at philnash.me
on Mastodon.
And of course, you can find all of that info and the show notes
on the Postcard website at cppcast.com.
The theme music for this episode is provided by podcastthemes.com.