Borrowing error while removing elements from vector on loop

Hello!

I am practicing rust and tried to write the following algorithm:

  • Given an array of integers
  • Remove elemens in array until it will be empty or index of the minimum element will be less than the index of the maximum element.

Here is the code

fn main() {
    let mut v = vec![7,1,5,3,6,4];
    let mut min = v.iter().min().unwrap();
    let mut max = v.iter().max().unwrap();
    
    while (!v.is_empty()) | 
          (v.iter().position(|x| x == min).unwrap() > v.iter().position(|x| x == max).unwrap()){
        v.remove( v.iter().position(|x| x == max).unwrap() );
        max = v.iter().max().unwrap();
    }
}

Than I've got the following error:

error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
  --> src/main.rs:11:9
   |
7  |     let mut min = v.iter().min().unwrap();
   |                   - immutable borrow occurs here
...
10 |     while (!v.is_empty()) | (v.iter().position(|x| x == min).unwrap() > v.iter().position(|x| x == max).unwrap()){
   |                                                         --- immutable borrow later captured here by closure
11 |         v.remove( v.iter().position(|x| x == max).unwrap() );
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here

How to solve this issue? When I remove the loop everything is ok.

What's happening here is:

  • min is a reference to an element of v, hence it borrowes it;
  • when you call remove every reference to the v's items is invalidated, which includes min;
  • when the loop executes again you use min, but it is now invalid.

A really simple fix would be to make min and max integers rather than references, so that they don't borrow v. You can do this by prepending v.iter().min().unwrap() with a *, for example let min = *v.iter().min().unwrap(), or by using the .copied() iterator adapter. You'll also have to add dereferences/.copied() when you search for the various positions since those will give you references and you now compare them with values.

fn main() {
    let mut v = vec![7,1,5,3,6,4];
    let mut min = *v.iter().min().unwrap();
    let mut max = *v.iter().max().unwrap();
    
    while (!v.is_empty()) | 
          (v.iter().position(|x| *x == min).unwrap() > v.iter().position(|x| *x == max).unwrap()){
        v.remove( v.iter().position(|x| *x == max).unwrap() );
        max = *v.iter().max().unwrap();
    }
}
1 Like

Thank you for the explanation.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.