【问题标题】:Rust match mutable enum reference with vectorsRust 将可变枚举引用与向量匹配
【发布时间】:2020-06-13 13:43:08
【问题描述】:

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

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 语句更改枚举的命名道具。但是我不明白为什么会发生移动,因为我是在借用枚举本身。代码如下:

        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

类型是:

  • StatementType 是派生克隆的枚举
  • Block 是 StatementType 的可变变量
  • 块的statementsVec&lt;Box&lt;StatementType&gt;&gt;的变量
  • block_statementsVec&lt;Box&lt;StatementType&gt;&gt; 的另一个变量

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

【问题讨论】:

  • 你能提供一个游乐场的例子吗?

标签: vector enums rust move


【解决方案1】:

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

使用您编写的代码,它是Vec&lt;_&gt; 类型(对不起,我说过),但是由于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 的类型为&amp;mut Vec&lt;_&gt;。您可以通过使用ref mut 捕获模式来实现:

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

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

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

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

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

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

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

【讨论】:

  • 谢谢,现在可以使用了。关于解决方案,您是说如果我使用 Vec(或任何未调整大小的类型),我需要使用 ref mut 捕获模式,对吗?
  • @Skai:这与未调整大小的类型无关。如果您想在不消耗整个对象的情况下捕获复杂类型的字段,则必须通过引用来捕获。 mut 只是为了获取可变引用,而不是常规引用。
  • @Skai: 之所以会出现关于未定型类型的奇怪对象,是因为您将运算符* 直接与Vec 一起使用,而不是引用,并且由于Vec 实现了Deref&lt;[T]&gt;,因此您得到了@987654342 @,没有大小,不能交换。
猜你喜欢
  • 1970-01-01
  • 2015-02-11
  • 1970-01-01
  • 1970-01-01
  • 2014-09-20
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
相关资源
最近更新 更多