it might do to wait until some other memory safe alternative appears.
it might do to wait until some other memory safe alternative appears.
And I don't understand how you can go from opining that Rust shouldn't be the only other option, to opining that they should have waited before supporting Rust. That doesn't make sense unless you just have a particular animus towards Rust.
But our opinions on this are irrelevant, as it turns out, unless you're actually Linus Torvalds hiding behind that throwaway account.
I don't think anyone is saying that Rust is the only way to achieve that. It is a way to achieve it, and it's a way that enough people are interested in working on in the context of the Linux kernel.
Ada just doesn't have enough developer momentum and community around it to be suitable here. And even if it did, you still have to pick one of the available choices. Much of that decision certainly is based on technical merits, but there's still enough weight put toward personal preference and more "squishy" measures. And that's fine! We're humans, and we don't make decisions solely based on logic.
> it might do to wait until some other memory safe alternative appears.
Perhaps, but maybe people recognize that it's already late to start making something as critical as the Linux kernel more safe from memory safety bugs, and waiting longer will only exacerbate the problem. Sometimes you need to work with what you have today, not what you hope materializes in the future.
It's slow because the potential benefits are slim and the costs of doing that research are high. The simple reality is that there just isn't enough funding going into that research to make it happen faster.
> there's no compelling reason that rust has to be the only way to achieve memory safety
The compelling reason is that it's the only way that has worked, that has reached a critical mass of talent and tooling availability that makes it suitable for use in Linux. There is no good Rust alternative waiting in the wings, not even in the kind of early-hype state where Rust was 15 years ago (Zig's safety properties are too weak), and we shouldn't let an imaginary better future stop us from making improvements in the present.
> it might do to wait until some other memory safe alternative appears.
That would mean waiting at least 10 years, and how many avoidable CVEs would you be subjecting every Linux user to in the meantime?
because it's hard enough that people don't try. and then they settle for rust. this is what i mean by "rust sucks the air out of the room".
however, its clearly not impossible, for example this authors incomplete example:
https://github.com/ityonemo/clr
> That would mean waiting at least 10 years,
what if it's not ten years, what if it could be six months? is or worth paying all the other downstream costs of rust?
youre risking getting trapped in a local minimum.
I think it's the opposite. Rust made memory safety without garbage collection happen (without an unusably long list of caveats like Ada or D) and showed that it was possible, there's far more interest in it now post-Rust (e.g. Linear Haskell, Zig's very existence, the C++ efforts with safety profiles etc.) than pre-Rust. In a world without Rust I don't think we'd be seeing more and better memory-safe non-GC languages, we'd just see that area not being worked on at all.
> however, its clearly not impossible, for example this authors incomplete example:
Incomplete examples are exactly what I'd expect to see if it was impossible. That kind of bolt-on checker is exactly the sort of thing people have tried for decades to make work for C, that has consistently failed. And even if that project was "complete", the hard part isn't the language spec, it's getting a critical mass of programmers and tooling.
> what if it's not ten years, what if it could be six months?
If the better post-Rust project hasn't appeared in the past 15 years, why should we believe it will suddenly appear in the next six months? And given that it's taken Rust ~15 years to go from being a promising project to being adopted in the kernel, even if there was a project now that was as promising as the Rust of 15 years ago, why should we think the kernel would be willing to adopt it so much more quickly?
And even if that did happen, how big is the potential benefit? I think most fans of Rust or Zig or any other language in this space would agree that the difference between C and any of them is much bigger than the difference between these languages.
> youre risking getting trapped in a local minimum.
It's a risk, sure. I think it's much smaller than the risk of staying with C forever because you were waiting for some vaporware better language to come along.
> youre risking getting trapped in a local minimum.
Or you are risking years of searching for perfect when you already have good enough.
A few that I found: logical operators do not short-circuit (so both sides of an or will execute even if the left side is true); it has two types of subprograms (subroutines and functions; the former returns no value while the latter returns a value); and you can't fall through on the Ada equivalent of a switch statement (select..case).
There are a few other oddities in there; no multiple inheritance (but it offers interfaces, so this type of design could just use composition).
I only perused the SPARK pdf (sorry, the first was 75 pages; I wasn't reading another 150), but it seemed to have several restrictions on working with bare memory.
On the plus side, Ada has explicit invariants that must be true on function entry & exit (can be violated within), pre- and post- conditions for subprograms, which can catch problems during the editing phase, and it offers sum types and product types.
Another downside is it's wordy. I won't go so far as to say verbose, but compared to a language like Rust, or even the C-like languages, there's not much shorthand.
It has a lot of the features we consider modern, but it doesn't look modern.
There are two syntaxes: `and` which doesn't short circuit, and `and then` which does. Ditto for `or` and `or else`.
C is actually more of an odd one here, and the fallthrough semantics is basically a side effect of it being a glorified computed goto (with "case" being literally labels, hence making things like Duff's device a possibility). Coincidentally, this is why it's called "switch", too - the name goes back all the way to the corresponding Algol-60 construct.
Before rejecting a reason you at least have to know what it is!
i think some people would argue RAII but you could trivially just make all deacquisition steps an explicit keyword that must take place in a valid program, and have something (possibly the compiler, possibly not) check that they're there.
There are other ways to achieve memory safety. Java's strategy is definitely a valid one; it's just not as suitable for systems programming. The strength of Rust's approach ultimately stems from its basis in affine types -- it is a general purpose and relatively rigorous (though not perfect, see https://blog.yoshuawuyts.com/linearity-and-control/) approach to managing resources.
One implication of this is that a point you raised in a message above this one, that "rust's default heap allocation can't be trivially used", actually doesn't connect. All variables in Rust -- stack allocated, allocated on the heap, allocated using a custom allocator like the one in Postgres extensions -- benefit from affine typing.
also you could have affine types without RAII. without macros, etc. etc.
theres a very wide space of options that are theoretically equivalent to what rust does that are worth exploring for devex reasons.
And remember that your gripes with Rust aren't everyone's gripes. Some of the things you hate about Rust can be things that other people love about Rust.
To me, I want all that stuff in the compiler. I don't want to have to run extra linters and validators and other crap to ensure I've done the right thing. I've found myself so much more productive in languages where the compiler succeeding means that everything that can (reasonably) be done to ensure correctness according to that language's guarantees has been checked and has passed.
Put another way, if lifetime checking was an external tool, and rustc would happily output binaries that violate lifetime rules, then you could not actually say that Rust is a memory-safe language. "Memory-safe if I do all this other stuff after the compiler tells me it's ok" is not memory-safe.
But sure, maybe you aren't persuaded by what I've said above. So what? Neither of us are Linux kernel maintainers, and what we think about this doesn't matter.
what you really should care about is: is your code memory safe, not is your language memory safe.
and this is what is so annoying about rust evangelists. To rust evangelists it's not about the code being memory safe (for example you bet your ass SEL4 is memory safe, even if the code is in C)
and also seL4 is about 10k lines of code, designed around verification, sequential, and already a landmark achievement of verification. linux is like 3 orders of magnitude more code, not designed around verification, and concurrent.
or a hpc workload for a physic simulation that gets run once on 400,000 cores, and if it doesnt crash on your test run it probably won't at scale.
if youre writing an OS, you will turn it on. in fact, even rust ecosystem suggests this as a strategy, for example, with MIRI.
I wouldn't argue that Rust is a good replacement for Makefiles, shell build scripts, Python scripts...
An amazing thing about Rust, though, is that you actually can write many "quick programs" -- application level programs -- and it's a reasonably good experience.
of course not, for kernel development. and in those cases, you WILL statically analyze.
Type systems are a form of static analysis tool, that is true; and in principle, they could be substituted by other such tools. Python has MyPy, for example, which provides a static analysis layer. Coverity has long been used on C and C++ projects. However, such tools can not "get out of the way of routine development" -- if they are going to check correctness of the program, they have to check the program; and routine development has to respond to those checks. Otherwise, how do you know, from commit to commit, that the code is sound?
The alternative is, as other posters have noted, that people don't run the static analysis tool; or run it rarely; both are antipatterns that create more problems relative to an incremental, granular approach to correctness.
Regarding macros and many other ergonomic features of Rust, those are orthogonal to affine types, that is true; but to the best of my knowledge, Rust is the only language with tightly integrated affine types that is also moderately widely used, moderately productive, has a reasonable build system, package infrastructure and documentation story.
So when you say "theres a very wide space of options that are theoretically equivalent to what rust does that are worth exploring for devex reasons.", what are those? And how theoretical are they?
It's probably true, for example, that dependently typed languages could be even better from a static safety standpoint; but it's not clear that we can tell a credible story of improving memory safety in the kernel (or mail servers, database servers, or other large projects) with those languages this year or next year or even five years from now. It is also hard to say what the "devex" story will be, because there is comparatively little to say about the ecosystem for such nascent technologies.
> how do you know, from commit to commit, that the code is sound?
these days its easy to turn full checks on every commit in origin; a pull request can in principle be rejected if any commit fails a test, and rewriting git history by squashing (annoying but not impossible) can get you past that if an intermediate failed.
It seems like, at least part of the time, you're discussing distinct use cases -- for example, the quick scripts you mention (https://news.ycombinator.com/item?id=43132877) -- some of which don't require the same level of attention as systems programming.
At other times, it seems like you're arguing it would be easier to develop a verified system if you only had to run the equivalent of Rust's borrow checker once in awhile -- on push or on release -- but given that all the code will eventually have to pass that bar, what are you gaining by delaying the check?