2

I'm storing some structs in a vector. In a loop I'm trying to process some input, and in every iteration I'd like to either insert a new item into the vector, or mutate an existing element (depending on whether it's already in the vector or not).

So I'm trying to do something like this.

struct Foo {
    id: char,
    data: i32,
}

fn main() {
    let mut cache: Vec<Foo> = Vec::new();

    for a in vec!['c'] {
        let foo = cache.iter_mut().filter(|s| s.id == a).nth(0);

        match foo {
            Some(f) => {
                f.data = f.data + 1;
            }
            None => {
                cache.push(Foo { id: a, data: 0 });
            }
        }
    }
}

I'm getting an error in the None arm saying

error[E0499]: cannot borrow `cache` as mutable more than once at a time
  --> src/main.rs:17:17
   |
10 |         let foo = cache.iter_mut().filter(|s| s.id == a).nth(0);
   |                   ----- first mutable borrow occurs here
...
17 |                 cache.push(Foo { id: a, data: 0 });
   |                 ^^^^^ second mutable borrow occurs here
...
20 |     }
   |     - first borrow ends here

What's the idiomatic way to avoid this issue? I tried the following workaround, which seems to work, but it feels very clunky.

for a in vec!['c'] {
    let mut found = false;

    {
        let step = cache.iter_mut().filter(|s| s.id == a).nth(0);

        match step {
            Some(f) => {
                f.data = f.data + 1;
                found = true;
            }
            None => (),
        }
    }

    if !found {
        cache.push(Foo { id: a, data: 0 });
    }
}

Is there an easier solution?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Mark Vincze
  • 7,737
  • 8
  • 42
  • 81
  • 3
    The easiest solution is to [switch to Rust 2018](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html) and your original code will work. – Shepmaster Dec 10 '18 at 21:28

0 Answers0