Two things, full time Rust dev here:
a) Rust's borrow checker is good and its type system good, but IMHO it's not really doing what you say it is as well as you're implying: "explaining in an explicit way who owns what"; While ownership is explicit and static (apart from RefCell and friends), description of that ownership is scattered all over, program state flows are not modelled in the type system at all, and on the whole Rust is far from having being a kind of explicit "I can reason about the whole program" declaritive system with the kind of clarity you're implying. Or maybe I'm taking your claims too strongly.
b) Rust's borrow checker is good. But it's not perfect and fails to pass things that in fact should be legal borrows. In particular there's edge cases around where things are grabbed in if/let/else or matches, like this fail (from my own code):
{
let local_version = self.seek_local(tx);
if local_version.is_some() {
return match &local_version.unwrap().value {
Entry::Value(v) => Some(v), // reference to value
Entry::Tombstone => None,
};
}
}
// note that 'local' has gone out of scope here and so self should not be borrowed
...
code later in func complains 'self' is still borrowed,
but the same thing done this way (but less efficiently) passes:
if self.seek_local(tx).is_some() {
let local_version = self.seek_local(tx).unwrap();
return match &local_version.value {
Entry::Value(v) => Some(v),
Entry::Tombstone => None,
};
}
...
same other code that uses 'self' compiles fine
In neither case is the 'local_version' being used outside of the lexical scope, and 'self' cannot be borrowed in either case, but the borrow checker is convinced in version #1 that they are and that code below that lexical scope cannot proceed because 'self' is borrowed. They're logically basically equivalent from a program flow and state mgmt, but the second passes while the first fails. Rust 1.7.0 stable.
(Before you ask, I did have if/let to take apart local_version instead of using unwrap, and the compiler griped about that even more)
Having the burden of how to fix that fall on the programmer sucks. This is all a step in the right direction, but I run into this kind of thing here and there and I shouldn't have to.