Continue Do references to mutable references need to be mutable?

The following code compiles,

let mut i = 0i32;
let j = {
    let r = &i; // immutable reference
    let rr = &r;
    &**rr
}

but the following failed

let mut i = 0i32;
let j = {
    let r = &mut i; // mutable reference
    let rr = &r;
    &**rr
}
error[E0597]: `r` does not live long enough
  --> demo.rs:21:18
   |
19 |     let j: &i32 = {
   |         - borrow later stored here
20 |         let r = &mut i;
21 |         let rr = &r;
   |                  ^^ borrowed value does not live long enough
22 |         &**rr
23 |     };
   |     - `r` dropped here while still borrowed

I have read the do-references-to-mutable-references-need-to-be-mutable, but still could not understand why the mutability of the borrow inside the scope was reported as a lifetime error.
I read this medium, but not quite satisfied with the explanation. Why doesn't the immutable version trigger a lifetime error?

Right, this is an interesting point. The difference is that if you have a double reference and flatten it, the lifetimes don't end up in the same way:

  • &'short &'long T becomes &'long T when flattened.
  • &'short &'long mut T becomes &'short T when flattened.

So the problem in your case is that if j has the lifetime 'long, it's fine, but it is not fine if it has the 'short lifetime.

The reason for this is that if you could get a &'long T in the second case, then it would be possible for the flattened reference to exist while the mutable reference is usable, but mutable references must have exclusive access. To illustrate:

fn main() {
    let mut i = 0i32;
    let r = &mut i;
    let j = {
        let rr = &r;
        &**rr
    };
    *r = 10;
    // println!("{}", j);
}

If you change the above code to use the println, then the mutable reference was not exclusive when you used it, and therefore it will fail to compile. However if r was immutable, then the above would be fine because immutable references are allowed to be shared.

7 Likes

Hi, @alice, thanks to your explanation I understand it now. By the way, where does such knowledge come from :laughing:? I don't remember the book says about this (I read it a year ago).

It is discussed in Rust: A unique perspective.

1 Like

What do you mean by “flattened”?

I mean going from &&T to &T and similar.