错误说值在循环迭代中移动到前一个,但这似乎不是真的

Error says value moved in previous in iteration of loop, but this doesn't seem true

如下面的代码所示,循环的每次迭代都定义了它自己的 Foo 实例,所以我看不出它是如何在“上一次循环迭代”中被“移动”的每个循环有一个新的 Foo

如何消除错误?

fn main() {
    for i in 0..2 {
        let vector: Foo;
        //  ------ move occurs because `vector` has type `Foo`, which does not implement the `Copy` trait
        if i == 0 {
            vector = Foo::Bar(vec![1_f32]);
        } else if i == 1 {
            vector = Foo::Baz(vec![1_u16]);
        }
    //  - value moved here, in previous iteration of loop
        println!("{}", vector.len());
        //             ^^^^^^ value used here after move
    }
}

enum Foo {
    Bar(Vec<f32>),
    Baz(Vec<u16>)
}

impl Foo {
    pub fn len(self) -> usize {
        match self {
            Foo::Bar(vector) => vector.len(),
            Foo::Baz(vector) => vector.len(),
            #[allow(unreachable_patterns)]
            _ => unreachable!()
        }
    }
}

通过使用 match 语句,我设法消除了错误。我不知道为什么这行得通而以前的代码却行不通:

fn main() {
    for i in 0..2 {
        let vector: Foo = match i {
            0 => Foo::Bar(vec![1_f32]),
            1 => Foo::Baz(vec![1_u16]),
            _ => unreachable!()
        };
        println!("{}", vector.len());
    }
}

您的 if-else 链并不详尽:

fn main() {
    for i in 0..2 {
        let vector: Foo;
        if i == 0 {
            vector = Foo::Bar(vec![1_f32]);
        } else if i == 1 {
            vector = Foo::Baz(vec![1_u16]);
        }

        // What should happen if `i` is not 0 or 1 ?
        // Then the app will try to use an uninitialized variable
        // The compiler cannot figure out that it is impossible 
        // with the current input  
        println!("{}", vector.len());
    }
}

因此当 i 不是 01 时,您必须添加一个 else 语句:

fn main() {
    for i in 0..2 {
        let vector: Foo;
        if i == 0 {
            vector = Foo::Bar(vec![1_f32]);
        } else if i == 1 {
            vector = Foo::Baz(vec![1_u16]);
        } else {
            unreachable!();
        }

        println!("{}", vector.len());
    }
}

或者最好使用 match 语句(如您自己的回答),因为它更清晰易读:

fn main() {
    for i in 0..2 {
        let vector: Foo = match i {
            0 => Foo::Bar(vec![1_f32]),
            1 => Foo::Baz(vec![1_u16]),
            _ => unreachable!() 
        };
        println!("{}", vector.len());
    }
}

相关问题(感谢@nneonneo):https://github.com/rust-lang/rust/issues/72649