A0A
A0A

Reputation: 118

Why does re-borrowing only work on de-referenced pointers?

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');
}

Upvotes: 1

Views: 422

Answers (1)

Shepmaster
Shepmaster

Reputation: 430368

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.

Upvotes: 4

Related Questions