4 ms·
I know about these, but there is a marked difference between Rust and these tools. Static analysis tools have much harder job analyzing C++ (aliasing and escap
by pornel 4y ago
I know about these, but there is a marked difference between Rust and these tools.
Static analysis tools have much harder job analyzing C++ (aliasing and escape analysis are way harder, and static analysis of thread-safety is basically impossible due to lack of thread-safety info in the type system). The results are a trade-off between being sparse or having false positives.
The sanitizers only catch issues they can observe at run time, and that relies on having sufficient test and fuzz coverage. Some data races are incredibly hard to reproduce, and might depend on a timing difference that won't happen in your test harness.
OTOH Rust proves absence of these issues by construction, at compile time.
It's like a difference between dynamically-typed and statically-typed languages. Sure, you can fuzz type errors out of JS or Python, but in statically-typed languages such errors are eliminated entirely at compile time. Rust extends this experience to more classes of errors.
- krona 4y agoThe results are a trade-off between sparse or having false positives. Rust just takes the other side of the trade-off, and will reject valid programs. Hence why the unsafe keyword exists, and why tools like Miri (https://github.com/rust-lang/miri https://github.com/rust-lang/miri) exist specifically for rust.
- timeon 4y ago> Rust just takes the other side of the trade-off, and will reject valid programs. Are we still talking about ease of add novice Rust programmers to a project?
- tialaramex 4y agoSure, that's the consequence of Rice's theorem. "Is this program correct?" is formally Undecidable, to dodge that we split the programs three ways: Correct, Not Correct, shrug emoji. It's obvious that Correct programs compile, Not Correct programs result in a compiler error, but what do we do with shrug emoji ? Rust says those go in the "Not Correct" pile and get a compiler error. C++ says - really, I'm not making this up - that they go in the Correct pile. There's an immediate short term consequence, but also, after decades, a long term consequence that's arguably worse. Short term, C++ programmers can't know if their non-trivial program is Correct. It might be complete horse shit, the compiler won't necessarily tell them. Long term, C++ grows worse and worse because there is no reason to shrink that shrug emoji category. All the programs in that category act as though they're fine, so there's no pressure whatsoever to improve the language standard, the compilers, etc.
- anyfoo 4y agoOver the decades, C started to reject more and more "valid" programs, and you have to use explicit casts to go from one pointer type to the other, or from an integer to a pointer. For obviously good reason.
- saghm 4y ago> Rust just takes the other side of the trade-off, and will reject valid programs This has always been such a weird claim to me because it's not clear to me what's meant by "valid". My instinct is that it would be hard to define valid in a way without making most languages either accept some invalid programs or reject some valid ones (the exception being defining "valid" as "anything that language X accepts", but that wouldn't really say anything interesting about Rust). Sure, you could draw the line so that Rust is the only one that rejects valid programs, but is it worse to be the only language that rejects some valid programs than to be a language that accepts invalid ones? The alternative is that all languages accept some valid programs, at which point there's nothing specific about Rust that's worse until you start specifying which valid programs each language rejects. If there's a way to define "valid" so that Rust is the only one that rejects valid programs but other languages accept all valid and reject all invalid programs, I think it's non-obvious enough that it should be explicitly stated.
- Omin 4y agoThat definition of what is valid or not depends on the type of checker. When you're talking about Rust's borrow checker, then you can take any property that it checks for, such as "there are no aliasing mutable references" or "any variable that is read from has been initialized" and build an example for it that would be correct, but is rejected by the borrow checker. Here is an example where a variable is definitely initialized, but it will be rejected. fn main() { let foo; if true { foo = 1; } println!("{}", foo); }
- djwatson24 4y ago> and that relies on having sufficient test and fuzz coverage At the faang I worked at, some small portion of servers ran the sanitizers in prod, so you’re not reliant on test coverage nearly so much for catching rare issues.