我可以在具有一个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
特征来执行此操作;这是编译器内部的硬编码能力。