问题
This question and code are adapted from Why does creating a mutable reference to a dereferenced mutable reference work?. The answers there explained re-borrowing but not the reasons for the conventions around it.
The two calls to test
below seem equivalent, why does only the first one work?
fn main() {
let mut string = String::new();
let ref_string = &mut string;
// Compiles
test(&mut *ref_string);
// Doesn't compile
test(&mut string);
}
fn test(s: &mut String) {
s.push('t');
}
回答1:
You are only allowed to have a single mutable reference to a value at a time. When you mutably reborrow as an argument, it's trivial for the compiler to see that you aren't going to be using ref_string
at the same time and thus the code is safe.
My mental image is that there's a "chain of custody" for the mutability. ref_string
is the holder and can temporarily give that up to the temporary created by &mut *ref_string
. When that goes out of scope, the mutability is returned to it. It's as if the code were:
{
let x = &mut *ref_string;
test(x);
}
However, when you try to "go around" and get the mutable reference, you are ignoring the chain of custody. The compiler stops you because it cannot trivially see that it is safe.
Of note is that non-lexical lifetimes improves the original situation. When the MIR-based borrow checker is enabled, the compiler can see that ref_string
is no longer in use by the time the second call to test
happens, thus it's safe for the exclusive access to be transferred there.
来源:https://stackoverflow.com/questions/51015503/why-does-re-borrowing-only-work-on-de-referenced-pointers