I don't think it's merely the Rust Evangelism Strike Force; Linus is notoriously critical of this kind of hype. In fact, his most vocal hatred of a programming language has been targeted at C++. Those criticisms almost surely have some amount of "lived experience" associated with them - he's not the kind of person to just buy into the hype of a programming language and risk the entire kernel over it.
Remember, this is the guy who used tarballs as a version control system up until Bitkeeper gave him free (as in beer) licenses to their DVCS. He didn't hate all version control, as much as he thought that was the case - he hated badly implemented version control, which was the standard at the time with things like CVS. That's why he ultimately wound up writing Git once the Bitkeeper deal became untenable.
In this set of old e-mails from a decade and change ago[0] he specifically calls out STL/Boost being unstable and difficult to work with, C++ providing certain abstractions that have undocumented performance problems, exception handling, and hidden allocations.
Of that list, I can think of several things Rust specifically solves relative to C++.
- Rust traits make reasoning about generic code way easier than C++ templates. In C++, you just write your template, and then the template is resolved at the site of instantiation. If it's not a valid type to put in there, then the compiler tells you that you used the template wrong, but it's still your responsibility to figure out why. In Rust, however, generic types have to be constrained with traits; which list out exactly what a generic type requires. So if you misuse a generic type, the compiler can just say 'well, you need Add on parameter T here to call this', and the error will always be on the type you used, rather than some dependent generic type.
- One of Rust's core goals is "zero-cost abstractions". It does this very well, but it also has some non-zero-cost abstractions. These I'd categorize as "transparent-and-predictable-cost abstractions". For example: Rust is known for it's borrow-checker, which provides compile-time verification of memory safety. However, these might not be the most flexible memory-management solution; so it also provides shared-ownership through reference counting. This does have an associated cost, but it's easy to reason about and clearly stated. They even provided both atomic and non-atomic reference counting options because the latter has less cost associated with it.
- C++ uses an exception handling model built around stack unwinding, which requires that all code maintain a valid stack that the C++ runtime can unwind at all times. This can pose problems for kernels which almost certainly will be doing weird things with the stack that the compiler won't entirely understand. While Rust has exceptions (called panics) and supports C++ style unwinding, it also allows you to change the exception handling model to just terminating the program instead, which matches better with how the Linux kernel handles exceptions.
- Rust also heavily discourages the use of exceptions relative to C++. Panicking is mostly reserved for error conditions that are actually exceptional (i.e. unexpected), while error conditions that are expected can be signaled using return types like Option and Result. There's even special language syntax (called Try, or the ? operator) which will automatically return if a value signals an error.
The only thing I can't say Rust solves is hidden allocations, but it seems like the plan Linus has picked is to tame that beast with a Linux-specific core library, with as much as possible mapped to Linux's existing C abstractions. This probably will work out as this is the intended way to extend existing native code with Rust libraries. (It's how Mozilla integrated things like Servo into Firefox.)
[0] http://harmful.cat-v.org/software/c++/linus