3

I was reading chapter Storing Lists of Values with Vectors . I was trying the example Attempting to add an element to a vector while holding a reference to an item.

let mut _v: Vec<i32> = vec![2, 4, 6];
let _first = &_v[0];
_v.push(8);
println!("{:?}", _first);

It didn't compile, as per expected behavior. According to the book:-

When the program has a valid reference, the borrow checker enforces the ownership and borrowing rules (covered in Chapter 4) to ensure this reference and any other references to the contents of the vector remain valid. Recall the rule that states you can’t have mutable and immutable references in the same scope. That rule applies in Listing 8-7, where we hold an immutable reference to the first element in a vector and try to add an element to the end, which won’t work.

But if I remove last println statement, the above code will compile. I am not able to understand how println! macro affect above statement.

Please let me know if I am missing anything.

hellow
  • 12,430
  • 7
  • 56
  • 79
Ayush Mishra
  • 567
  • 1
  • 7
  • 19
  • 3
    Variable names should only be prefixed with underscore (`_`) when they are not used, yet you are using both `v` and `first`. – E_net4 Apr 17 '19 at 09:27

1 Answers1

9

With the introduction of Non-Lexical Lifetimes (NLL), lifetimes of borrows are often shortened if they don't need to be longer. If you try to compile your example without the println! in the 2015 edition of Rust (which doesn't have NLL, as far as I know), you get a compile error (playground link).

Even with NLL, the print statement forces the borrow of _v[0] to last at least until after the printing is done. But that means that the borrow begins before and ends after the mutable borrow _v.push(8). That can't happen since mutable borrows must be exclusive borrows.

But without the print statement, the borrow of _v[0] can end right away, allowing the mutable borrow to happen.

SCappella
  • 9,534
  • 1
  • 26
  • 35