2
fn f<'a>(_: &'a mut &'a u8) {}

fn main() {
    let mut data = &1;
    {
        let tmp_mut = &mut data;
        f(tmp_mut);
    }
    println!("{:p}", data);
}

Playground

error[E0502]: cannot borrow `data` as immutable because it is also borrowed as mutable
  --> src/main.rs:11:22
   |
8  |         let tmp_mut = &mut data;
   |                            ---- mutable borrow occurs here
...
11 |     println!("{:p}", data);
   |                      ^^^^ immutable borrow occurs here
12 | }
   | - mutable borrow ends here

This code can be fixed by not using the same lifetime in the function signature (just leave fn f(_: &mut &u8) {}), but what exactly is going on here?

The error message looks a little bit strange - it seems counterintuitive that tmp_mut tries to live more than the block where it was declared. I would expect the error message to grumble about impossible lifetime requirements, not about a uniqueness error.

Stargateur
  • 24,473
  • 8
  • 65
  • 91
ozkriff
  • 1,269
  • 15
  • 23
  • I believe your question is answered by the answers of [Mutable borrow seems to outlive its scope](https://stackoverflow.com/q/32403837/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 20 '18 at 15:30
  • Yeah, thanks, I guess it's essentially the same question. – ozkriff Aug 20 '18 at 15:51
  • @Shepmaster, I do not think this is duplicate. @Matthieu M. 's answer only explains how to get rid of the error. The code in the new question was cleared of all unnecessary and clearly shows the borrowchecker's weird behavior. I belive that the fact that borrowing continues beyond the scope where `tmp_mut` was defined can not be explained with equality of lifetimes or invariance. – aSpex Aug 21 '18 at 09:50
  • 1
    @aSpex I disagree. Matthieu's answer contains the phrase "you *told* the compiler that you wanted both lifetimes to be the same!" which is exactly the reason the mutable borrow has to be no shorter than the lifetime of `tmp_mut`: *because you said so*. I don't understand your objection here, because there is clearly no lifetime that satisfies all the requirements. – trent Aug 22 '18 at 14:49
  • 2
    [Why does linking lifetimes matter only with mutable references?](https://stackoverflow.com/questions/32165917/why-does-linking-lifetimes-matter-only-with-mutable-references) is another closely related question. – trent Aug 22 '18 at 14:56
  • Thanks for that link. > "there is clearly no lifetime that satisfies all the requirements" Why do you think so? The scope of the `main()` satisfies the requrements. The compiler does not complain that it can not infer the lifetime. It complains that `data` is borrowed. If you remove `println()` in the last line, then the code will run without errors. We can deliberately create a situation where the lifetime can not be infer. Change `data` defenition to `let mut data:&'static u8 = &1;` Now the compiler says that `data does not live long enough`. – aSpex Aug 23 '18 at 06:41
  • > "which is exactly the reason the mutable borrow has to be no shorter than the lifetime of `tmp_mut`". I cant agree whith this. In my opinion, it is the reason why `tmp_mut` can not outlive `data`. Duration of mutable borrowing should be determined only by the inner scope in which `tmp_mut` is declared. – aSpex Aug 23 '18 at 07:11
  • I have not seen any exceptions to this rule in the Rust book, Rustonomicon or wherever else. – aSpex Aug 23 '18 at 07:19
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/178618/discussion-between-trentcl-and-aspex). – trent Aug 23 '18 at 13:23

0 Answers0