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



我正在尝试更改枚举的命名属性,但收到此错误。

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

类型有:

  • 语句类型是派生克隆的枚举
  • 块是语句类型的可变变量
  • 块的statementsVec<Box<StatementType>>的变量
  • block_statementsVec<Box<StatementType>>的另一个变量

请不要说它发生是因为语句的类型是 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

有一种叫做匹配人体工程学的东西,它允许你匹配引用并省略ref mut捕获模式,这使你的代码更容易编写和理解:

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

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

最新更新