在降低后,将带有多个值的枚举匹配的枚举时,使用移动值

  • 本文关键字:枚举 移动 rust pattern-matching
  • 更新时间 :
  • 英文 :


我可以在具有一个String参数的enum上使用模式匹配:

extern crate robots;
use std::any::Any;
use robots::actors::{Actor, ActorCell};
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
    Msg { param_a: String },
}
pub struct Dummy {}
impl Actor for Dummy {
    // Using `Any` is required for actors in RobotS
    fn receive(&self, message: Box<Any>, _context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
            match *message {
                ExampleMessage::Msg { param_a } => println!("got message"),
            }
        }
    }
}

但是我无法在2个参数上执行枚举匹配的模式:

#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
    Msg { param_a: String, param_b: usize },
}
impl Actor for Dummy {
    // Using `Any` is required for actors in RobotS
    fn receive(&self, message: Box<Any>, _context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
            match *message {
                ExampleMessage::Msg { param_a, param_b } => println!("got message"),
            }
        }
    }
}

这会导致错误:

error[E0382]: use of moved value: `message`
  --> src/example.rs:19:48
   |
19 |                 ExampleMessage::Msg { param_a, param_b } => {
   |                                       -------  ^^^^^^^ value used here after move
   |                                       |
   |                                       value moved here
   |
   = note: move occurs because `message.param_a` has type `std::string::String`, which does not implement the `Copy` trait

我尝试在相同的enum上匹配模式,而之前却没有降低呼吸,这很好,但是我需要降低。对我来说,这似乎是非常奇怪的行为,我不知道如何绕过这个错误。

我正在使用Rust 1.19.0-oftighly(AFA1240E5 2017-04-29(

我尝试在同一枚举上匹配模式,而不降低降低,这很好

这是减少问题的良好尝试。问题是您减少了太远。将Box<T>降低到Foo不返回Foo,它返回Box<Foo>

fn downcast<T>(self) -> Result<Box<T>, Box<Any + 'static>> 

您可以通过:

重现问题
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
    Msg { param_a: String, param_b: usize },
}
fn receive2(message: Box<ExampleMessage>) {
    match *message {
        ExampleMessage::Msg { param_a, param_b } => println!("got message"),
    }
}
fn main() {}

好消息

这是借用检查器的当前实现的限制,当启用非遗传寿命时,您的原始代码将如下工作:

#![feature(nll)]
#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
    Msg { param_a: String, param_b: usize },
}
fn receive2(message: Box<ExampleMessage>) {
    match *message {
        ExampleMessage::Msg { param_a, param_b } => println!("got message"),
    }
}
fn main() {}

当前现实

非时光寿命和基于mir的借用检查器尚不稳定!

当您匹配与偏置的值时,该值通常不移动。这使您可以做类似的事情:

enum Foo {
    One,
    Two,
}
fn main() {
    let f = &Foo::One;
    match *f {
        Foo::One => {}
        Foo::Two => {}
    }
}

在这种情况下,您希望将Box 1 内部的事物拥有,以便在match中破坏该领域的所有权。您可以通过在尝试匹配的之前将价值从包装盒中移出。

漫长的做法是:

fn receive2(message: Box<ExampleMessage>) {
    let message = *message;
    match message {
        ExampleMessage::Msg { param_a, param_b } => println!("got message"),
    }
}

,但您也可以使用卷曲括号来强迫移动:

fn receive2(message: Box<ExampleMessage>) {
    match {*message} {
        ExampleMessage::Msg { param_a, param_b } => println!("got message"),
    }
}

我不完全理解为什么一个字段会起作用;当然是不一致的。我唯一的猜测Box的所有权移动到第一个参数,提取了参数,然后编译器试图再次将其移至下一个参数。


1 - 通过*移出所包含的元素是只有Box支持的特殊功能。例如,如果您尝试使用参考来执行此操作,则会获得"无法移出借来的内容"错误。您也不能实现Deref特征来执行此操作;这是编译器内部的硬编码能力。

最新更新