简体   繁体   中英

Rust compiler complaining of using moved value in loop when code is not

Rust is complaining of using a moved value in a loop:

#[derive(PartialEq, Eq)]
enum Animal {
    Dog,
    Cat,
}

fn dedup(animals: Vec<Animal>) -> Vec<Animal> {
    let mut stage = None;
    let mut outs = vec![];

    for x in animals {
        match stage {
            None => stage = Some(x),
            Some(a) => {
                if a != x {
                    outs.push(a);
                    stage = Some(x);
                }
            }
        }
    }
    if let Some(a) = stage {
        outs.push(a);
    }
    outs
}

The error message is:

error[E0382]: use of moved value
  --> src/lib.rs:14:18
   |
14 |             Some(a) => {
   |                  ^ value moved here, in previous iteration of loop
   |

When I read this code, I see that stage is moved into a , which is then possibly pushed to outs , then never used again. Why is this a compiler error?

Playground

Interestingly, the following alternative works:

            Some(a) if a != x => {
                    outs.push(a);
                    stage = Some(x);
            }
            _ => {}

When you write

match stage {
    // ...
    Some(a) => {
        // ...
    }
}

you are unconditionally moving the value out of stage . It doesn't matter if the code in the block uses a or not; all Rust sees is that the stage is now invalidated, and cannot be used again.

The reason why

Some(a) if a != x => {
    outs.push(a);
    stage = Some(x);
}

works is because including the if in the pattern makes it a conditional move. The a is only moved out if a != x , and when that happens, stage is always reassigned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM