In general my opinion is that all of chapter 4 in the book needs a rewrite, and that the community as a whole needs better introductory material about borrowing that does not
- conflate value liveness with Rust lifetimes
- say or imply that Rust lifetimes are intrinsically scope based
- say things like "the lifetimes are chosen at the call site"
One can explain reborrows without this background material, and an example or two is often enough to let someone learning Rust get the gist and continue on with their learning. So maybe it's not a hard blocker. But I feel it's somewhat incomplete or feels more magic that it needs to if you have some misconceptions about borrows more fundamentally.
Some comments on some of the links follow. Some of the comments may of limited usefulness unless you already have a mental model of borrowing close to mine...
Haibane Tenshi
The problem with their "emulating reborrows" is that the reference itself is borrowed, instead of reborrowing the referent. It's the same thing I'm getting at here. Incidentally, the only time a reference going out of scope matters to borrow checking is when the reference itself is borrowed. Which is one of those things most existing learning material gets wrong. (I.e. this is related to why I think we need better introductory material on borrows more generally.)
They are correct that we can't express reborrows with traits or existing function APIs so far.
Their "liveness scope" isn't really how the compiler works. Value liveness scopes have no associated Rust lifetime and are not inherited by borrow lifetimes. Their stacked borrows citation should probably be an NLL (or Polonius) citation. I didn't put in enough work to understand their mental model enough to grasp their 'l+'r1
suggestion, but it might make sense if you could designate a place with 'l
instead of some "liveness". I skipped the "scope expansion" section since they'd already lost me.
Reference #788
Not a learning resource, but I'll just note that subtypes and coercions do not explain reborrowing. Those don't let you "duplicate" a non-Copy
value like &mut _
reborrowing does. Or to create some lifetime relationships but not others based on the presence of a nested &_
somewhere.
SO 62960584
Good answer
.
SO 30535529
Their second example compiles with NLL (since Rust 1.36 edition 2015 / 1.31 edition 2018). Learning pre-NLL borrow checking isn't very productive, probably.
Questions about &mut T
and move semantics
I mostly skimmed it.
Stacked borrows -- or an alternative, Tree borrows -- or some other future alternative -- are about the operational semantics. What the borrow checker does in safe code, like reborrows, will always be a compile-time checkable subset of what the opsem model allows. They can still be useful in terms of providing a mental model of why something is accepted, e.g. a stack of reborrows.
Someone mentions Rust by Example, but that needs a rewrite too IMNSHO.
This is inaccurate in a couple ways,
- the reference itself isn't borrowed with reborrowing, as covered above
- reborrows definitely can have the same lifetime as the original borrow, that's how
&mut _
getters work