# Can't borrow vec elements twice

In my problem I have a vector-based computations that modifies its element based on the value of its other elements. The following example of a running sum may serve as a simplified toy problem:

``````#[derive(Copy, Clone)]
struct X{x:i16}

fn running_sum(a:&X, b:&X, c:&mut X) {
c.x = a.x + b.x;
}

fn main() {
const N: usize = 10
let mut row = [X{x:0};N];
for i in 0..N-2 {
running_sum(&row[i], &row[i+1], &mut row[i+2]);
}
println!("{} {} {}", &row.x, &row.x, &row.x);
}
``````

It simply evaluates x[i] = x[i-1] + x[i-2]. This obviously doesn't work, because:

``````error[E0502]: cannot borrow `row[_]` as mutable because it is also borrowed as immutable
--> src/main.rs:11:35
|
11 |     running_sum(&row, &row, &mut row);
|     ----------- -------           ^^^^^^^^^^^ mutable borrow occurs here
|     |           |
|     |           immutable borrow occurs here
|     immutable borrow later used by call
``````

I fully understand the reason; the question is how to make it compile?

Please don't advice putting the `c.x = a.x + b.x;` into the `for` loop of the main program. This is exactly the situation I have now. In my real case that inner calculation involves a lot of math and I want to refactor it by breaking into parts.

The only solution (not specific to rust) that comes to my mind is to refactor `running_sum()` into: `running_sum(row: &mut &[X], pos: usize)`;

Any rust-specific solution that would solve the double-borrow problem?

Here’s a way to make it work:

``````for i in 0..N-2 {
let [a, b, c] = &mut row[i..i+3] else {
unreachable!();  // ^^^^^^^^
};                   //   +-- or: `row[i..][..3]`
running_sum(a, b, c);
}
``````

In the future, for convenient and fully flexible access to multiple elements of a vec/array/slice, we might also eventually be able to use the (still unstable) get_many_mut API.

Stable solutions of accessing multiple elements of a slice mutably at the same time, include slice patterns as demonstrated in the code above, and the more flexible split_at_mut method, which can help achieve the same for non-subsequent elements of a slice.

1. or partially mutably ↩︎

2. For example, here’s one way to use it in this code example:

``````for i in 0..N-2 {
let (row_init, row_i_plus_2) = row.split_at_mut(i+2);
running_sum(&row_init[i], &row_init[i+1], &mut row_i_plus_2);
}
``````
↩︎
6 Likes

Another alternative.

``````    let mut borrow = &mut row[..];
while let [a, b, c, ..] = borrow {
running_sum(a, b, c);
borrow = &mut borrow[1..];
}
``````

This is basically an inlined `mut` version of `windows,` which can't exist as a standard `Iterator` due to the aliasing. But there may be a lending iterator crate that provides it.

5 Likes

The other solutions are better in this particular case, but I recently had to do a similar computation where the elements were not contiguous in the array. In that case I used `split_at_mut(x, i)`.