3 ms·
P.S. > Notice that the working approaches have something important in common: a strong system that, given certain assumptions, guarantees the lack of memory sa
by pron 7y ago
P.S.
> Notice that the working approaches have something important in common: a strong system that, given certain assumptions, guarantees the lack of memory safety problems.
That's a very good point and I'm not arguing against it. It's just that even if it's true -- and I'm more than willing to concede that it is -- it still doesn't answer the question, which is: what is the best approach to achieving a required level of correctness?
The "soundness" approach says, let's guarantee, with some caveats, certain technical correctness properties that we can guarantee at some reasonable cost. The problem is that that cost is still not zero, and my hypothesis is that it's not negligible. My personal perspective is that Rust might be sacrificing too much for that, but that's not even what has disappointed me with Rust the most. I think -- and I could be wrong -- that Rust sacrifices more than it has to just to achieve that soundness, by also paying for "zero-cost abstractions," which, for my taste, is repeating C++'s biggest mistake, namely sacrificing complexity for the appearance of high-level abstraction that may look convincing when you read the finished code (perhaps more convincing in Rust than in C++), but falls apart when you try to change it. Once you try to change the code you're faced with the reality that low-level languages have low abstraction; i.e. they expose their technical details, whether it's through code -- as in C and Zig -- or through the type system, as in Rust. Zig says, since the abstraction in low-level languages is low anyway (i.e. we cannot really hide technical details) there is little reason to pay in complexity for so-called zero-cost abstractions.
Language simplicity goes a long way, even as far as sound formal verification is concerned. For example, there are existing sound static analysis tools that can guarantee no UB for C -- but not the complete C++, AFAIK -- with relatively little effort. It's not yet clear to me whether Zig, with its comptime, is simple enough for that, though.
It is my great interest in software correctness, together with my personal aesthetic preferences, that has made me dislike language complexity so much and made me a believer in "when in doubt -- leave it out."
- mntmoss 7y agoI would like to chime in by noting that Rust's mature form is borne of a very specific scenario, which is the web browser, software so complex that the "zero-cost" element is more like "actually possible to optimize" in practice. And a great deal of that complexity is accidential in some form, a result of accreted layers. And in that respect, it's not really the kind of software anyone needs to aspire to; aspiring to write programs simple enough that Zig will do the job is much more palatable.
- pron 7y agoI don't take issue with the "zero-cost" part -- Zig and C, like every low-level language, have that -- but with the non-abstraction-"abstraction" part, which is rather unique to C++ and Rust. Rust has become a modern take on C++, and I'm not sure it had to be that for the sake of safety; I think it became that because of what you said: it was designed to replace C++ in a certain application with certain requirements. It's probably an improvement over C++, but, having never been a big fan of C++, it's not what I want from a modern systems programming language. It seems to me that Rust tries to answer the question "how can we make C++ better?" while Zig tries to answer the question "how can we make systems programming better?" Of course, Zig has an unfair advantage here in that it is not production-ready yet, and so it's not really "out there," and doesn't have to carry the burden of any real software (there's very little software that Rust carries, but it's still much more than Zig). I admit that when Rust was at that state I had the same hopes for Rust as I do now for Zig, so Zig might yet disappoint.
- pcwalton 7y ago> I think -- and I could be wrong -- that Rust sacrifices more than it has to just to achieve that soundness, by also paying for "zero-cost abstractions," which, for my taste, is repeating C++'s biggest mistake, namely sacrificing complexity for the appearance of high-level abstraction that may look convincing when you read the finished code (perhaps more convincing in Rust than in C++), but falls apart when you try to change it. The argument here seems to be that there is can be no real abstraction in low-level languages, so there's no point providing language features for abstraction. The premise seems clearly false to me, because even C has plenty of abstraction. Functions are abstractions. Private symbols are abstractions. Even local variables are abstractions (over the stack vs. registers). People often argue that Rust is too complicated for its goal of memory safety. It's easy to say that, but it's a lot harder to list specific features that Rust has that shouldn't be there. In fact, as far as I'm concerned Rust is an exercise in minimal language design, as the development of Rust from 0.6-1.0 makes clear (features were being thrown out left and right). Most of the features that look like they're there solely to support "zero-cost abstractions"—traits, for example—are really needed to achieve memory safety too. For instance, Deref is central to the concept of smart pointers, and, without smart pointers, users would have to manually write Arc/Rc/Box in unsafe code every time they wanted to heap-allocate something. > Language simplicity goes a long way, even as far as sound formal verification is concerned. For example, there are existing sound static analysis tools that can guarantee no UB for C -- but not the complete C++, AFAIK -- with relatively little effort. It's not yet clear to me whether Zig, with its comptime, is simple enough for that, though. The most important static analyzers used in industry today are Clang's sanitizers, which work on both C and C++. The most important such sanitizers actually work at the LLVM level, which means they work on Rust as well [1]! The days of having to write a compiler frontend for static analysis are long gone. We have excellent shared compiler infrastructure that makes it easy to write instrumentation that targets many low-level languages at once. (Even in the world of C, this is necessary. Plain old C99 is an increasingly marginal language, because the real important code, such as Windows and Linux kernels, are written in compiler-specific dialects of C, which means that a static analysis tool that isn't integrated with some popular compiler infrastructure will have limited usefulness anyway.) > It is my great interest in software correctness, together with my personal aesthetic preferences, that has made me dislike language complexity so much and made me a believer in "when in doubt -- leave it out." Again: easy to say, harder to specify specific Rust features you think should be removed. [1]: https://github.com/japaric/rust-san https://github.com/japaric/rust-san
- littlestymaar 7y ago> For example, there are existing sound static analysis tools that can guarantee no UB for C -- but not the complete C++, AFAIK -- with relatively little effort. The only static analysis tools that can guarantee anything about C are doomed to have plenty of false positives. They are much less used in practice than tools ASan & co which don't guarantee anything but have way fewer false positive, if any. They have their use-case, but calling them “little effort” is disingenuous.
- pron 7y ago> The only static analysis tools that can guarantee anything about C are doomed to have plenty of false positives. That's where the effort comes in. Those false positives are removed by adding annotations or changing code. > They have their use-case, but calling them “little effort” is disingenuous. I said they require relatively little effort, because it's definitely less effort than a rewrite in Rust. This isn't hypothetical. >1MLOC programs in the industry today are checked in this way. If you have an existing large C program and decide that you need your program to have no UB, those sound static analysis tools are the most cost-effective way of doing that today.
- littlestymaar 7y ago> That's where the effort comes in. Those false positives are removed by adding annotations or changing code. With the former you lose all guarantees and fall back to a safe/unsafe duality, with the latter you need to rethink how your code works to comply yo the analyzer's mindset: in the end it's pretty much like Rust, but in an ad-hoc way, much less ergonomic. > I said they require relatively little effort, because it's definitely less effort than a rewrite in Rust. This is a ridiculous way to save your argument. You are well aware that this is not what “relatively easy” means. It is comparatively easier to deploy such tools than to rewrite a whole project in Rust, but the payoff is also lower in the long run (Rust offers more than zero-UB), so we might get to a point (when tooling[1] and hiring pool have reached a point where it becomes sustainable) where the latter option makes more sense for most people (unless C is mandatory, for portability reasons for instance). [1]: I'm especially thinking about C2Rust here https://immunant.com/blog/2020/01/quake3/ https://immunant.com/blog/2020/01/quake3/