"cannot borrow as mutable because it is also borrowed as immutable" in the same statement

When I try to compile this code:

pub struct Foo {
    x: i32,
    arr: Vec<i32>
}

impl Foo {
    pub fn get_x(&mut self) -> i32 {
        self.x
    }
}

pub fn bar() -> i32 {
    let mut a = Foo { x : 2, arr: [1, 2, 3].into() };
    a.arr[a.get_x() as usize]
}

I get this error:

error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable
  --> <source>:14:11
   |
14 |     a.arr[a.get_x() as usize]
   |     ------^^^^^^^^^----------
   |     |     |
   |     |     mutable borrow occurs here
   |     immutable borrow occurs here
   |     immutable borrow later used here

(I know this is a contrived example.)

Can someone please explain to me why I get this error?

I'd assume that a.get_x() is evaluated and executed strictly before a.arr is accessed. Therefore only one reference would be alive at any point. But somehow the Rust compiler is still complaining about it.

If I split this statement into two lines, it compiles without errors.

This is because the array lookup is syntax-sugar for this:

Index::index(&a.arr, a.get_x() as usize);

This desugars to:

let arg1 = &a.arr;
let arg2 = a.get_x() as usize;
Index::index(arg1, arg2);
2 Likes

That makes sense. Thanks a lot @alice !