I do hope that Rust doesn't suffer from an explosion in complexity and compile times, though. Memory safety and overengineering shouldn't have to go hand in hand.
I do hope that Rust doesn't suffer from an explosion in complexity and compile times, though. Memory safety and overengineering shouldn't have to go hand in hand.
And many of these were _bad_, C++ was a different language back then and the culture of how you write C++ was different. There were times when it was fashionable to write OO spaghetti almost as bad as the stereotypes about java, or templates that worked except for some unforeseen footgun (then you could template libraries that worked correctly but figuring out how was a trip). And before all of that there was a decade when C++ compilers were just _full_ of bugs, and before that there was no standard and every compiler was different. The negative stereotypes about C++ come from all that.
I think he had every reason to fear that e.g. he would have to fight someone who implemented control flow using an inheritance hierarchy because it's a pattern. And he could find himself in the minority.
(Also I'd say there are still counterproductive fads, and it's still common to write C++ that's beautiful on the outside and completely inscrutable inside, or generally pay a huge price in code size and complexity for marginal gains elsewhere, or to depend on optimizations that don't trigger. Same in many other higher-level languages but somehow not in C.)
Second, more important, i don't remember any talk of adapting C++ to bare metal programming, while there is an ongoing cooperation with rust folks already.
C++ already is used in bare metal environments and in at least one production kernel (XNU) so there just isn't any adapting to do. The standard explicitly distinguishes between hosted and freestanding environments and defines what you should expect to have available.
That does not mean you would try to use virtual functions (much), or std::vector or std::shared_ptr (ever). Instead, you would use abstractions tailored precisely to the kernel environment, and arrange that wrong code would tend to not compile, so that when code compiles, it works. In C, you have to enforce all conventions by obeying instructions in comment blocks, and updating all uses every time the comment block changes. In C++, you can encode the rules directly into the type system and put that to work, not just checking correctness, but actually generating correctness.
This is the same as one would do in Rust modules. Failing to make full use of Rust's type system would be a grave mistake that we need not fear will happen.
Since I'm on mobile, here's a link to a previous explanation of mine: https://news.ycombinator.com/item?id=1422160 It is meant to be read in conjunction with the original post, addressing what I saw as the point most people were missing, not a complete restatement of his points.
Your post also mentions operator overloading, which is a bit nastier since the calls aren’t explicit. But Rust also has operator overloading, so similar complaints would probably apply? In practice I’d expect the kernel to be fairly strict about limiting operator overloading (which would apply for both C++ hypothetically as well as Rust).
I can't directly speak to Rust's overloading support. If it's still one static type lookup he may be ok with it, plus you have the clarity around ownership of any intervening constructions. I'm sure the Rust Evangelism Strike Force (awesome 80s cartoon music intensifies) will be along presently to answer the question of how much assembler one can generate with an overloaded operator.
C++ really does have a particular ability to stack a huge number of abstractions into one little line. Ultimately it's a continuum rather than a sharp line, but C++ is really far on one side.
I did get your point but would like to point out that using these slurs isn't helping any discussion.
There are fanatics in every area everywhere. Their existence doesn't devalue any of the bigger groups they belong to. Their existence is a fact of life.
I've worked with plenty of Rust devs (and I am an aspiring one myself although not all the way there yet) and I've only ever seen hard-working people with an excellent eye for detail and desire to maximally utilize the hardware and have better safety than other languages they worked with in the past. Zero fanatics.
Just at the moment, C++ is notably better at this, in important cases, but I gather there are plans for Rust to adopt more of C++'s capabilities. The Rust designers fully understand the cases I mention, but are very busy.
Linus's ignorant diatribe about C++ tells us plenty about Linus, but nothing meaningful about C++ or its suitability for kernel coding. That every detail he rails about in C++ applies equally to Rust is unintentionally revealing. That each such detail makes C++ and Rust better for large systems, moreso.
Take some vintage C++ code from late nineties, like games, and there's no concept of ownership, before smart pointers and move, and full of global's everywhere.
It was also when code were transitioning for a multi-threading era, so using the same code style of the previous sequential era was really bad.
Of course, all the new features C++ gained since '98 only make the language more useful for coding large, long-lived systems, as is amply demonstrated in the tens or hundreds of billions of lines of C++ code implementing exactly those systems. Rust's adoption of so many of those same features increases its usefulness for a growing number of those same purposes.
To me C++ is a language of last resort. It can do everything you need but you should not touch it if there is any other option.
Building from your metaphor, I would add:
Python et al.: normal household batteries; everyone can use/operate them, not much power but can be used with little to no training and a screwup happening means you went looking for trouble
Java et al.: electric batteries; substantially more power but has to stop relatively often (GC pauses), everyone can use the things running on them at least reasonably well [0] but one little thing can potentially cause a catastrophic chain reaction (one cell out of thousands => thermal runaway (eg. the infamous NullPointerException))
Rust, Go et al.: industrial backup generators or hydroelectric plants; substantially more power yet again but have a startup/setup time (learning a more complicated language/ecosystem), as reliable as can be realistically done but have to be spec'd right for the building/installation/etc. at hand (time vs. resources tradeoffs); screwups happening means you probably went looking for trouble (eg. in Rust: excessive cloning of data, building of circular references without weak references; not so sure about specific examples in Go but didn't want to lump it together with Java et al.)
C, C++ et al.: "nuclear power [...] very powerful but dangerous if only used slightly wrong" like in your metaphor; should only really be used by experts but even they are not safe from introducing catastrophic failures with something seemingly harmless (seen as such at the time of writing the code); it gets safer over time but there is the huge inertia of existing installations running with huge time and resource costs associated with dismantling or even modernisations; footguns are everywhere and not always immediately recognisable especially since there recommendations about usage and safety concerns floating around which are sometimes years or decades out of date
[0]: AFAICT a substantial part of the business software world runs on Java code cobbled together by not-necessarily-full-on-experts
PS: My personal experiences/biases:
- learned C++11 for a while, didn't like it, SEGFAULTs and associated debugging/fine-tooth-combing over the some-tens-or-hundreds-of-lines long code got really annoying really quickly
- learned Java, Haskell and Prolog in Uni; Haskell was a nice intro to functional programming but nothing I would want to use even occasionally, Prolog was meh, Java was/is a convoluted, resource-hungry mess with huge amounts of boilerplate for every little thing and will IMHO always be associated with bad assignments in class(es)
- Python3 I use every other week or so but not for "real programming (TM)", but instead for small (automation/download/crawler) scripts; I like it but for serious programming in a business environment - ie. something I personally would want to rely on for money - the duck-typing is just too unstable for my liking, even though I still like it for rapid prototyping of concepts coming into my head which I then later may or may not transfer into:
- Rust... currently and personally my favorite language for "real programming (TM)" even though I struggled with the borrow checker for a long, long time (and still run into it on occasion); sometimes really long compile times but nice runtime performance in most cases even without special care and tuning while I still have the confidence that if it compiles it runs and any errors encountered at testing-/runtime are probably more due to logic errors than running into something like "oops, in this deep branch of cascading ifs I accidently didn't set some object's field or dict's value meaning at some later point the program blew up due to NoneError or something similar"
- learned a bit of Go (before even finding out about Rust) but I just didn't like it, it just didn't "gel with me", don't even really remember the specific reason(s)
Also,
> but has to stop relatively often (GC pauses)
is severely outdated and I don’t see how NPEs are something specific to Java.
Shorter pause times than Go.
These are bad comparisons.
Google chose C++ 17 as the implementation language of the Zircon kernel for the fuchsia OS.
https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/...
PS: C++ compile times are actually shorter than rust compile times.
For this kind of project its more important to have people with pratical experience in kernels, than experience in a particular language.
These people will have a experience in languages they used before, so even if the decision was taken today, you wouldn't find enough people with experience in kernels AND Rust, but will have much more people with experience in kernels C and/or C++, so C++ would still be a good default in comparison to C.
It would be pretty amateurish to get the kernel expert folks to learn Rust while implementing it, as it would probably mean that the end result in Rust would be worse than the end result in C++ as they were more comfortable and experienced in that language.
It will take more time to form specialists in some key areas so that decision can be made with less side-effects.