2017-05-02 1 views
1

를 downcasting 후 여러 값을 열거 일치하는 패턴 :사용 때 한 <code>String</code> 매개 변수가있는 <code>enum</code>에 일치하는 패턴을 사용할 수 있습니다

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"), 
      } 
     } 
    } 
} 

그리고 아직 내가 열거 패턴 매칭을 수행 할 수 없습니다 오전

#[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 
012,351,641 2 개 매개 변수

이전에 다운 캐스팅하지 않고 동일한에 패턴 일치를 시도했는데 정상적으로 작동하지만 다운 캐스트가 필요합니다. 이것은 매우 이상한 행동으로 보입니다. 나는이 오류를 우회하는 법을 모릅니다.

내가 (2017년 4월 29일 afa1240e5) 녹 1.19.0 - 야간 사용하고

답변

4

I tried pattern matching on the same enum without downcasting before, and this works fine

이 문제를 줄이는 좋은 시도이다. 문제는 당신이 너무 멀리 감소했다는 것입니다.

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

는 당신이 문제를 재현 할 수 있습니다하십시오 Box<T>Foo A를 Downcasting 것은 Foo, it returns a Box<Foo>는 반환하지 않습니다

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

내가 알고있는 것처럼, 때 당신이 역 참조 된 값과 일치의 값이 이 아니고이 (가) 정상적으로 이동했습니다. 이 allows you to do something like :이 경우

enum Foo { 
    One, 
    Two, 
} 

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

, 당신은 match에서 그것을 destructuring 때 필드의 소유권을하기 위해 Box1 내부의 물건의 소유권을하고 싶습니다. 일치시키려는 시도가이되기 전에 밖으로 값을 이동하여이 작업을 수행 할 수 있습니다.

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의 소유권이 첫 번째 매개 변수로 이동되고 param이 추출 된 다음 컴파일러가 다음 매개 변수로 다시 이동하려고 시도한다는 것입니다.

오류 메시지에 대한 녹 문제를 검색하거나 존재하지 않는 오류 메시지를 만드는 것이 합리적이라고 생각합니다.


1은 - *를 통해 포함 된 요소를 이동하면 만 Box 지원하는 특별한 힘이다. 예를 들어 참조로이 작업을 수행하려고하면 "차용 한 콘텐츠에서 벗어날 수 없음"오류가 발생합니다.이 작업을 수행하려면 Deref 특성을 구현할 수 없습니다. 이것은 컴파일러 내에서 하드 코딩 된 기능입니다.

+0

내 정신 모형을 수정하는 데 아주 힘든 시간을 보내고 있습니다 ... 원래 버전의'receive2 '는 무엇이 잘못 되었습니까? 왜 단일 struct 필드 만 바인딩 할 때 문제가 사라지나요? 'Box <> '가 특별하기 때문에 뭔가 관련이 있습니까? 또한 - 어떤 특별한 힘을 말하는 겁니까? Thanks Shep – user1935361

+1

@ user1935361 조금 더 많은 텍스트를 추가했습니다. – Shepmaster

+0

[1]에 대해서 - 왜냐하면'Deref'는 항상 참조를 반환하기 때문에 나는 그것을 얻었을 것이라고 생각합니다. – user1935361

관련 문제