user24500634
user24500634

Reputation: 11

Understanding Rust borrows/references when looping over vector

I am struggling to find a way on how to solve following problem in Rust. I want to be able to loop over a (mutable) vector and still be able to loop over the same vector nested in the outer one.

struct Test {
    value: i32,
}

fn main() {

    let mut vec = [Test{value: 1}, Test{value: 2}, Test{value: 3}];

    for el in vec.iter_mut(){
        println!("{}", el.value);

        for a in vec.iter_mut(){
            println!("Inner {}", a.value);
        }
        el.value = 10;
    }
}

is resultin in an error caused by the borrow checker:

error[E0499]: cannot borrow `vec` as mutable more than once at a time
  --> src\main.rs:12:18
   |
9  |     for el in vec.iter_mut(){
   |               --------------
   |               |
   |               first mutable borrow occurs here
   |               first borrow later used here
...
12 |         for a in vec.iter_mut(){
   |                  ^^^ second mutable borrow occurs here

Upvotes: 0

Views: 86

Answers (2)

true equals false
true equals false

Reputation: 793

Assuming Test can be copy, this is achievable by using std::cell::Cell: (playground)

use std::cell::Cell;

#[derive(Debug, Copy, Clone)]
struct Test {
    value: i32,
}

fn main() {
    let mut vec = [Test{value: 1}, Test{value: 2}, Test{value: 3}];
    let vec: &Cell<[Test]> = Cell::from_mut(vec.as_mut_slice());
    let vec: &[Cell<Test>] = vec.as_slice_of_cells();
    for el in vec.iter() {
        for a in vec.iter() {
            // use `a`
            dbg!(a.get().value);
        }
        // Mutate
        el.set(Test {value: 10});
    }
}

If Test is not copy, this method can still be used, but unsafe may be necessary.

Upvotes: 1

Timmmm
Timmmm

Reputation: 96547

Yeah you can't do that, even though it does seem almost reasonable (if you dropped el before the inner loop at least). I think the fundamental issue is that Rust doesn't distinguish between your mutable access to the elements of vec, and vec itself (e.g. to change its length).

It doesn't actually know that vec.iter_mut() isn't going to remove or reorder elements. And if it did, that would obviously break the outer loop.

Depending on what you want to do you can do it using indexes (in C style), or maybe by manipulating iterators.

Upvotes: 1

Related Questions