Add ref to vec, modify var, access vec then gives borrow of x occurs here

#1

I think it peculiar that line 10 is the one that triggers the compiler error. I don’t understand why x is being borrowed at line 6

fn main() {
    let mut x: i32 = 5;
    // assert_eq!(x,5);
    let mut i32_vec: Vec<&i32> = Vec::new();

    i32_vec.push(&x); //this is a reference why is it borrowed that errors when line 10 is active
    // assert_eq!(x,5); //why isn't this saying that it is borrowed already?
    x = 6;
    println!("{}", x);
    // println!("{}", i32_vec[0]); //uncommenting this line will result in
                                //       |
                                // 6  |     i32_vec.push(&x);
                                //   |                  -- borrow of `x` occurs here
                                // ...
                                // 10 |     x = 6;
                                //   |     ^^^^^ assignment to borrowed `x` occurs here
                                // ...
                                // 13 |     println!("{}",i32_vec[0]); //commenting out this line will result in
                                //   |                   ------- borrow later used here
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0506]: cannot assign to `x` because it is borrowed
  --> src/main.rs:8:5
   |
6  |     i32_vec.push(&x);
   |                  -- borrow of `x` occurs here
7  |     // assert_eq!(x,5); //why isn't this saying that it is borrowed already?
8  |     x = 6;
   |     ^^^^^ assignment to borrowed `x` occurs here
9  |     println!("{}",x);
10 |     println!("{}",i32_vec[0]); //uncommenting this line will result in
   |                   ------- borrow later used here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0506`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

0 Likes

#2

If you have a look at the source of the assert_eq macro you will see that it does only borrows x again which is ok. (here).

Changing x to 6 is only ok, if x is not borrowed anymore, which depends on the fact if i32_vec is used again or not.

0 Likes

#3

x is borrowed immutably, (&x), so it is guaranteed that as long as the reference to x exists, it will not change. Ie, as long as a reference to x, be it mutable &mut x or immutable &x, the original owner of x cannot mutate it, unless it is through functions associated with the owner of the reference (If it is a mutable reference). When you push a reference to x into i32_vec you’re guaranteeing that it will not change.

0 Likes