Post by Alexei A. Frounze[snip]
It's a bit of a joke that all new Rust programmers go through
a phase of, "fighting the borrow-checker." (Followed shortly by
the "traits are AWESOME, let's use them EVERYWHERE!" phase).
:) I'm not fighting it (yet). I think I get the basic idea (or one of the
few) that the allocations/lifetimes are nested (entirely or largely,
unless we're using the unsafe escapes), but I got confused with
some details and put it aside. Should work out those details at
some point.
Conceptually, it's fairly simple:
1. Every non-trivial[*] object has a single owner
2. Assignment is logically a "move" operation, not copy, and
transfers ownership of the object
3. Objects are immutable by default.
3. You can either borrow a single mutable reference to a mutable
object, or one or more immutable references to any object,
but these are mutually exclusive:
a. if a mutable refence to an object exists, you cannot
borrow another reference of any kind to the same object;
b. if any number of refenences to an object exists you cannot
borrow a mutable refence to that object.
Note that (a) and (b) together imply that you can create as
many immutable references to an object as you like.
4. A reference may not outlive the object it is borrowed from,
and lifetimes are a first-class property in the language,
with explicit language support.
The interesting thing is that, in safe Rust code, all of this is
statically enforced by the compiler, and the combination has
some interesting properties. Safe Rust code is, by definition,
free of data-races; further, the existence of a mutable
reference is a compiler-enforced proof of the right to mutually
exclusive access to a valid object (references are defined to
be non-nullable). Undefined behavior in safe Rust is a
compile-time error.
Unsafe Rust lets you do a handful of other things (like
dereference raw pointers), but the programmer must still obey
all of the above rules. Effectively, `unsafe` says that the
compiler cannot check the rules statically, so the programmer is
asserting that they have all been followed using external
knowledge that the compiler is not privy to.
Post by Alexei A. FrounzePersonally, I like just cracking it open and playing around with
a language to learn it, but that's just me.
I was hoping, I'd just read the relevant chapters, but I might
end up doing just the same, writing code as aid. I expect my code
compiling and working being more of a proof of the soundness
of the code with rust than with C/C++. Though I think rust
still got some things wrong (e.g. different overflow handling in
debug vs release), but overall it seems a step in the right direction.
Perhaps, a few steps, not just one. :)
Yes; safe Rust code that successfully compiles is essentially
statically free of entire classes of memory safety problems, and
more or less cannot segfault.
An observation when we started programming in it at work was
that it took us longer to get our programs to compile, but once
we did, they tended not to have memory-safety issues. That
doesn't mean that they didn't have bugs, but the defects were
more often logic issues rather than bad pointers and so on.
Moreover, where we used `unsafe` was where we really needed to
go look and see if we were messing something up in our reviews.
I tend to agree wth you about e.g. overflow handling, though we
also found that because we were thinking about it for the debug
case, we used the explicit versions if we really wanted wrapping
semantics and so on, and where we wanted the checks even in
release mode we could use `checked_add` and so on. Still, there
is an argument that it would have been better if checked were
the default, and the unchecked kind had to be explicitly
requested. One nice thing in this area is that generally, Rust
is explicit in places where other languages are implicit:
conversion between types, for example.
I think they got a few things wrong in the memory model,
frankly, and the way that allocators work can be challenging if
you neither need more want infallible semantics for allocation.
It's not prefect, but right now, it's pretty good; I've enjoyed
programming bare-metal at a higher level of abstraction than one
gets out of C, for example.
- Dan C.