Rust 编译器抱怨在代码不存在时在循环中使用移动的值

pur*_*tii 3 rust

Rust 抱怨在循环中使用移动的值:

#[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
}
Run Code Online (Sandbox Code Playgroud)

错误信息是:

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

当我阅读这段代码时,我看到它stage被移入a,然后可能被推到outs,然后再也没有使用过。为什么这是编译器错误?

操场

有趣的是,以下替代方法有效:

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

Lam*_*iry 5

当你写

match stage {
    // ...
    Some(a) => {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

无条件地将值移出stage. 块中的代码是否使用a并不重要;Rust 所看到的stage只是现在已失效,无法再次使用。

之所以

Some(a) if a != x => {
    outs.push(a);
    stage = Some(x);
}
Run Code Online (Sandbox Code Playgroud)

有效是因为if在模式中包含 使其成为有条件的移动。该a只搬走了,如果a != x和这种情况发生时,stage总是重新分配。

  • 非常明确地说,对于像我这样错过了大约 5 次要点的人来说:当 `stage` 是 `Some(a)` 且 `a == x` 时,在原始代码中,`stage` 被移出了 *不*立即重新分配,因此不能在下一次迭代中再次移出。 (2认同)