The RFC is somewhat misleading, too. It is authoritative, but it is conflict with rustc,
The key point here is that we create a reference r
by reborrowing **q
; r
is then later used in the final line of the program. This use of r
must extend the lifetime of the borrows used to create both p
and q
. Otherwise, one could access (and mutate) the same memory through both *r
and *p
. (In fact, the real rustc did in its early days have a soundness bug much like this one.)
It is inaccurate. According to the text, the lifetime used for creating p and q must be extended to forbid *r, *p to access the same memory.
While, they needn't to extend. When you access the memory via *q, q is alive, the aliveness requires 'q and 'p exists. If your accessing is via *p, then only 'p is required to alive, 'q is not needed.
The key point is like uncertainty principle
in quantum mechanics. You observe it, you change it. When you writing code to show the necessary of some lifetime, the code itself produces the necessity.
Because dereferencing a mutable reference does not stop the supporting prefixes from being enumerated, the supporting prefixes of **q
are **q
, *q
, and q
. Therefore, we add two reborrow constraints: 'q: 'r
and 'p: 'r
, and hence both borrows are indeed considered in scope at the line in question.
This is correct, but means nothing.
For the following code:
fn main() {
let mut a = 1;
let mut b = &mut a;
let m = {
let mut c = &mut b; // 'c
let mut n = &*c; // 'n
n
};
println!("{}", n);
}
It is the scope lifetime of c matters, not 'c, it is not same, and what we are dropping is c.
When n moves out into main as m, 'c still there, while c, gone.
So,
let m = {
let mut c = &mut b; // 'c
let mut n = &*c; // 'n
drop(c);
n
};
fails because of shadowing, it is ok to drop c, but fails because of drop c makes using of c while n is reborrowing *c.