0

get() returns a reference to a vector item, pushing the value beforehand if necessary:

struct Container {
    vec: Vec<i32>,
}
impl Container {
    fn find(&mut self, v: i32) -> Option<&mut i32> {
        None // we don't care the implementation
    }

    fn get(&mut self, v: i32) -> &mut i32 {
        match self.find(v) {
            Some(x) => x,
            None => {
                self.vec.push(v);
                self.vec.last_mut().unwrap()
            }
        }
    }
}

fn main() {
    let mut container = Container { vec: Vec::new() };
    let x = container.get(42);
}

It does not compile because self is still borrowed when we try to push the value (self.vec.push(v)):

error[E0499]: cannot borrow `self.vec` as mutable more than once at a time
  --> test.rs:13:17
   |
10 |         match self.find(v) {
   |               ---- first mutable borrow occurs here
...
13 |                 self.vec.push(v);
   |                 ^^^^^^^^ second mutable borrow occurs here
...
17 |     }
   |     - first borrow ends here

This is due to non-lexical lifetime.

So as a workaround, I thought I could rewrite get() to limit the scope of self.find():

fn get(&mut self, v: i32) -> &mut i32 {
    if let Some(x) = self.find(v) {
        return x;
    }
    self.vec.push(v);
    self.vec.last_mut().unwrap()
}

Unfortunately, this does not work:

error[E0499]: cannot borrow `self.vec` as mutable more than once at a time
  --> test.rs:13:9
   |
10 |         if let Some(x) = self.find(v) {
   |                          ---- first mutable borrow occurs here
...
13 |         self.vec.push(v);
   |         ^^^^^^^^ second mutable borrow occurs here
14 |         self.vec.last_mut().unwrap()
15 |     }
   |     - first borrow ends here

I can't understand why.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
rom1v
  • 2,752
  • 3
  • 21
  • 47
  • Probably a dupe of https://stackoverflow.com/q/30243606/155423 – Shepmaster Jun 07 '17 at 16:01
  • The problem is very similar, but different in that my if-block returns the unwrapped value (as `&mut i32`), so the accepted workaround in the other post (which is in fact similar to my failing sample) does not apply here. – rom1v Jun 07 '17 at 16:37
  • 3
    @rom1v, https://stackoverflow.com/q/38023871/2731452 – red75prime Jun 07 '17 at 16:59
  • Thank you for this link, which perfectly answers my question. – rom1v Jun 07 '17 at 20:35

0 Answers0