fn main(){
let mut v = 0;
let mrf = & mut v;
let rf = &*mrf;
println!("{}",mrf);
}
This example is ok. However, we say the mutable borrow excludes the immutable borrow. Desugar the lifetime of the above example will get the following diagram:
'v:{
let mut v = 0;
'a:{
let mrf = & mut v; // ------------------------------- the mutable borrow mrf begins
'b:{
let rf = &*mrf; // --------------------------- the immutable borrow begins
} // --------------------------- rf ends
println!("{}",mrf); // ------------------------------- mrf ends
}
}
It can be seen that the lifetime of the immutable reference overlaps with the lifetime of the mutable borrow. However, the compiler can pass through this example. What's the reason here?
Immutable borrow is created by reborrowing the mutable one, so, strictly speaking, they don't coexist - the mutable borrow is temporarily rendered unusable, as long as its reborrow exists.
The original borrow, from which the re-borrow was created, is unusable as long as the re-borrow is in use. So the diagram you created isn't a correct illustration of the situation. You should temporarily end the validity of the original borrow when the re-borrow starts, and restart its validity once the re-borrow ends.
In general, lifetimes and regions are not expressible using scopes only; that's too simplistic a mental model. You need to take control flow into account, too.
fn main(){
let mut v = 0;
let mrf = & mut v;
let rf = &*mrf;
println!("{}",mrf); // #1
println!("{}",rf); // #2
}
You said:
The original borrow, from which the re-borrow was created, is unusable as long as the re-borrow is in use.
The reborrow rf is used at #2, according to your interpretation, the original borrow should keep being unusable until #2. The actual is, it can still be used at #1.
The answer to that is that "the &mut borrow is unusable" is a slight simplification. More accurate is "the &mut borrow acts like a & borrow."
So a fuller picture could be
// `place` begins
let mut place = 0;
// '1 is derived from `place`
// `place` mayn't be used
// '1 may be used by-mut
let uniq: &'1 mut i32 = &mut place;
// '2 is derived from '1
// '2 mayn't be used by-mut
// '1 mayn't be used by-mut
let shr: &'2 i32 = &*uniq;
// '1 is used by-ref
dbg!(uniq);
// '2 is used by-ref
dbg!(shr);
// '2 ends
// '1 may again be used by-mut
// '1 ends
// `place` may again be used
// `place` ends