Rust doesn’t magically make the vast majority of bugs go away. Most of bugs are entirely portable!
Rust doesn’t magically make the vast majority of bugs go away. Most of bugs are entirely portable!
So for example today I dealt with a synchronization issue. This turned out to not be a code bug but a human misunderstanding of a protocol specification saga, which was not possible to code into a type system of any sort. The day before was a constraint network specification error. In both cases the code was entirely irrelevant to the problem.
Literally all I deal with are human problems.
My point is Rust doesn't help with these at all, however clever you get. It is no different to C, but C will give you a superset of vulnerabilities on top of that.
Fundamentally Rust solves no problems I have. Because the problems that matter are human ones. We are too obsessed with the microscopic problems of programming languages and type systems and not concentrating on making quality software which is far more than just "Rust makes all my problems go away" because it doesn't. It kills a small class of problems which aren't relevant to a lot of domains.
(incidentally the problems above are implemented in a subset of c++)
I run into those things nearly daily, so... ok then.
Maybe not in a reasonable language no, but there are advances in type systems that are making ever larger classes of behaviours encodable into types. For example, algebraic effects (can this function throw, call a remote service etc)
https://koka-lang.github.io/koka/doc/index.html
linear types (this method must be called only once etc)
https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/line...
dependent typing (f(1) returning a different type from f(2), verifiable at compile time),
https://fstar-lang.org/index.html
Some of these features will eventually make it to “normal” PL. For example, Scala now has dependent types,
https://dotty.epfl.ch/docs/reference/new-types/match-types.h...
and Java can support linear type checking,
You might say that the C and Rust code will have the same number of logic errors, but I'm not convinced that's the case either. Sure, if you just directly translate the C to Rust, maybe. But if you rewrite the C program in Rust while making good use of Rust's type system, it's likely you'll have fewer logic errors in the Rust code as well.
Rust has other nice features that will help avoid bugs you might write in a C program, like most Result-returning functions in the stdlib being marked #[must_use], or match expressions being exhaustive, to name a couple things.
Actually it's a bit cleverer than that, and some people might benefit from knowing this. The Result type itself is marked #[must_use]. If you're writing a Goat library and you are confident that just discarding a Goat is almost always a mistake regardless of the context in which they got a Goat you too should mark your Goat type #[must_use = "this `Goat` should be handled properly according to the Holy Laws of the Amazing Goat God"] and now everybody is required to do that or explicitly opt out even for their own Goat code.
Obviously don't do this for types which you can imagine reasonable people might actually discard, only the ones where every discard is a weird special case.
Types I like in Rust which help you avoid writing errors the compiler itself couldn't possibly catch:
Duration - wait are these timeouts in seconds or milliseconds? It's different on Windows? What does zero mean, forever or instant ?
std::cmp::Ordering - this Doodad is Less than the other one
OwnedFd - it's "just" a file descriptor, in C this would be an integer, except, this is always a file descriptor, it can't be "oops, we didn't open a file" or the count of lines, or anything else, we can't Add these together because that's nonsense, they're not really integers at all.
[1]: https://www.chromium.org/Home/chromium-security/memory-safet...
I have written a lot of C and Rust. The notion that identical projects written in both languages would have identical numbers of (or even severity of) bugs is laughable on its face.
I mean, literally just not being able to deref a NULL pointer by itself is enormous.
let p: *const i32 = std::ptr::null(); // Pointer to a signed 32-bit integer, but it's null
unsafe { some_local = *p }; // Dereferencing the null pointer, bang
If we instead use references they're nicer to work with, don't need unsafe, perform the same, and are never null. So obviously that's what real Rust programmers almost always do.In practice I have never encountered a null pointer in Rust. Most Rust programmers have never encountered a null pointer. For most non-FFI practical purposes you can act as if they don’t exist.
> akshually they have same amount of bugs
You literally segfault by dereferencing invalid pointer.
But: If you are LUCKY! The worse case is if you DON'T segfault by dereferencing invalid pointer.