Rust 将可变枚举引用与向量匹配

Rust match mutable enum reference with vectors

我正在尝试更改枚举的 命名为 属性 但出现此错误。

cannot move out of a mutable referencerustc(E0507)
parser.rs(323, 36): data moved here
parser.rs(323, 36): move occurs because `statements` has type `std::vec::Vec<std::boxed::Box<ast::ast::StatementType>>`, which does not implement the `Copy` trait

我看到我们可以使用匹配语句更改枚举的命名属性。但我不明白为什么会发生移动,因为我借用了枚举本身。这是代码:

        match &mut block {
            StatementType::Block { mut statements, .. } => {
                statements = block_statements;
            },
            _ => panic!()
        };
        return block;

我也试过 mem::swap 但还是一样的错误:

        match &mut block {
            StatementType::Block { mut statements, .. } => {
                // statements = block_statements;
                std::mem::swap(&mut statements, &mut block_statements);
            },
            _ => panic!()
        };
        return block;

但是 当我这样做时:

                std::mem::swap(&mut *statements, &mut *block_statements);

错误变为:

the size for values of type `[std::boxed::Box<ast::ast::StatementType>]` cannot be known at compilation time

doesn't have a size known at compile-time

类型是:

请不要说它会发生,因为语句的类型是 Vector:请提供解决方案,因为我也可以读取错误消息。

您必须考虑 statements 的类型以及您希望它成为什么类型。

用你写的代码,它是 Vec<_> 类型(对不起,我说了),但是由于 match 通过引用捕获块,它不能通过值,因此错误。请注意,错误不在赋值中,而是在匹配大括号本身中:

error[E0507]: cannot move out of a mutable reference
  --> src/main.rs:15:11
   |
15 |     match &mut block {
   |           ^^^^^^^^^^
16 |         StatementType::Block { mut statements, .. } => {
   |                                --------------
   |                                |
   |                                data moved here
   |                                move occurs because `statements` has type `std::vec::Vec<std::boxed::Box<StatementType>>`, which does not implement the `Copy` trait

您当然希望 statement 属于 &mut Vec<_> 类型。您可以通过使用 ref mut 捕获模式获得它:

    match block {
        StatementType::Block { ref mut statements, .. } => {
            *statements = block_statements;
        },
        _ => panic!()
    };

并且记得在分配时使用 *statement,因为它现在是一个引用。如果你愿意,你也可以使用 mem::swap,当然:

            std::mem::swap(statements, &mut block_statements);

但请注意,您不需要match &mut block,但您可以直接match block

有一个叫做 match ergonomics 的东西可以让你匹配参考并省略 ref mut 捕获模式,这让你的代码更容易编写和理解:

    match &mut block {
        StatementType::Block { statements, .. } => {
            *statements = block_statements;
        },
        _ => panic!()
    };

您的原始代码中的问题是,如果指定任何捕获模式,则会禁用匹配人体工程学。