Confused about reborrow

fn rr(a: &String) {}
fn main() {
    let mut a = String::from("abc");
    let b = &mut a;//mutable borrow occurs here
    let c = &*b;//immutable borrow occurs here
    rr(b);//mutable borrow later used here
    rr(c);//immutable borrow later used here
}

It can work.
But why mutable borrow and immutable borrow can cross use

1 Like

There is a read-only reborrow in rr(b), you can think of it as rr(&*b).

No actual mutable/exclusive reference overlaps with shared references since (2), thus it compiles.

// MIR instructions on the right comments
// Try it yourself in playground's drop buttom on left top bar
fn rr(a: &String) {}
fn main() {
    let mut a = String::from("abc"); // _1 = <String as From<&str>>::from(const "abc")
    let b = &mut a; // _2 = &mut _1; (2)
    let c = &*b; // _3 = &(*_2);
    rr(b); // _5 = &(*_2); _4 = rr(move _5)
    rr(c); // _6 = rr(_3)
}
2 Likes

Shared reborrows invalidate overlapping exclusive borrows, but not other shared borrows.

Another example:

2 Likes

thank all reply.
I found an answer that solved my confusion

1 Like

thx, good tutorial

I'm sorry to bother you again, I watched your tutorial but there's a sentence in your tutorial that I don't understand “ You cannot get a &'long mut U through dereferencing a &'short mut &'long mut U

This fails, for example.

fn example<'long, 'short>(nested: &'short mut &'long mut String) -> &'long mut String {
    &mut **nested
}

Once the outer &'short mut _ "expires", the inner &'long mut String it is borrowing must once again be exclusive. So when you reborrow through the outer &'short mut _, you can only reborrow a &'short mut String.

That's why the error says...

error: lifetime may not live long enough
 --> src/lib.rs:2:5
  |
1 | fn example<'long, 'short>(nested: &'short mut &'long mut String) -> &'long mut String {
  |            -----  ------ lifetime `'short` defined here
  |            |
  |            lifetime `'long` defined here
2 |     &mut **nested
  |     ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'long` but it is returning data with lifetime `'short`

...that you're returning data with lifetime 'short.


The error also says:

  = help: consider adding the following bound: `'short: 'long`

That does make things compile, but we need a little more information to understand why. In our signature, the input argument nested has type:

nested: &'short mut &'long mut String

This carries with it an implied bound of 'long: 'short, because it's invalid for the nested reference to even exist if this bound doesn't hold. When you combine this bound with 'short: 'long, it forces both the lifetimes to be equal. Just like if you had the following inequalities:

x <= y
y <= x

So if you follow the help, you'll have a

nested: &'long mut &'long mut String

which may make the function compile, but usually causes problems elsewhere.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.