Why does the borrow checker reject the following code?
fn foo(a: &mut u32, b: u32) {
*a += b;
}
fn main() {
let mut x = Vec::new();
x.push(0);
x.push(1);
for i in 2..10 {
x.push(x[i - 1]);
foo(&mut x[i], x[i - 2]);
}
dbg!(&x);
}
Using rustc 1.39.0, I see the error
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
--> src/main.rs:11:24
|
11 | foo(&mut x[i], x[i - 2]);
| --- - ^ immutable borrow occurs here
| | |
| | mutable borrow occurs here
| mutable borrow later used by call
In general, can a function take a mutable reference to an element of a slice if it also takes a copy of another element from the same slice?
You need to split up your code for the borrow checker to be happy.
fn foo(a: &mut u32, b: u32) {
*a += b;
}
fn main() {
let mut x = Vec::new();
x.push(0);
x.push(1);
for i in 2..10 {
x.push(x[i - 1]);
let bar = x[i - 2];
foo(&mut x[i], bar);
}
dbg!(&x);
}
The borrow checker looks in right to left order to try and find where borrows overlap. So, &mut x[i] overlaps with x[i - 2], because it's borrow only ends after the function foo returns
This is likely due to how $x.$method($args) is desugared, and I don't know enough of the subtleties of this desugaring to give an answer. It may just be special cased to work.