Move error in for-loop when not reborrowing a mutable slice

Viewed 917

I'm trying to pass a mutable slice to a function and use it in several loops inside it.

function1 produces an error. Changing to function2 or function3 makes the errors disappear, but I don't understand the differences between function1 and function2. v and &mut *v seem similar to me.

Why doesn't function1 work while the others do?

fn main() {
    let mut v = Vec::new();

    function1(&mut v);
    function2(&mut v);
    function3(&mut v);
}

// Move Error 
fn function1(v: &mut [i32]) {
    for l in v {}
    for l in v {} // <-- Error Here !!!
}

// Works Fine
fn function2(v: &mut [i32]) {
    for l in &mut *v {}
    for l in &mut *v {}
}

// Works Fine
fn function3(v: &mut [i32]) {
    for l in v.iter_mut() {}
    for l in v.iter_mut() {}
}

The error:

error[E0382]: use of moved value: `v`
  --> src/main.rs:12:14
   |
11 |     for l in v {}
   |              - value moved here
12 |     for l in v {} // <-- Error Here !!!
   |              ^ value used here after move
   |
   = note: move occurs because `v` has type `&mut [i32]`, which does not implement the `Copy` trait
1 Answers

&mut *v is doing a so-called "reborrow".

This means that instead of iterating over the original reference, you are iterating over a new reference.

Think about it this way:


If you have an owned vector, and you iterate over it, then you get the same error if you try iterating over it again, because it has been moved into the for loop.

If instead you borrow the vector and iterate over the borrow, then you can do that as many times as you want.


If you have a mutable borrow, and you iterate over it, then you are moving the mutable borrow into the for loop. So it's gone now.

If instead you create a new reference pointing into the mutable borrow, you are just moving out of the new reference. Once the iteration finishes, the new mutable borrow is gone, meaning that the original mutable borrow can be accessed again.

Related