简体   繁体   中英

Extract Boxed enum from a enum in rust

I am writing an interpreter for a Scheme-like language in Rust. I coded the AST as an enum:

#[derive(Debug)]
pub enum Object {
    Integer(i64),
    Boolean(bool),
    Character(char),
    String(String),
    Symbol(String),
    Cons { car: Box<Object>, cdr: Box<Object> },
    Nil,
}

pub type ObjectBox = Box<Object>;

I wanted to add a car(&self) -> ObjectBox method to Object . I came up with:

impl Object {
    pub fn car(&self) -> Option<ObjectBox> {
        match self {
            Object::Cons { car, cdr: _ } => Some(ObjectBox::new(**car)),
            _ => None,
        }
    }
}

On compiling I get this error:

error[E0507]: cannot move out of `**car` which is behind a shared reference
  --> src/core/object.rs:94:65
   |
94 |             Object::Cons { car, cdr: _ } => Some(ObjectBox::new(**car)),
   |                                                                 ^^^^^ move occurs because `**car` has type `object::Object`, which does not implement the `Copy` trait

For more information about this error, try `rustc --explain E0507`.

I understand why the error is happening, but I am unable to come up with a way to fix it. Can this be done with my current Object implementation?

You cannot move out of a &self , so you have few options:

  1. Consume self :
impl Object {
    pub fn car(self) -> Option<ObjectBox> {
        match self {
            Object::Cons { car, cdr: _ } => Some(ObjectBox::new(*car)),
            _ => None,
        }
    }
}

Playground

  1. Return a reference:
pub type ObjectBox<'a> = Box<&'a Object>;

impl Object {
    pub fn car(&self) -> Option<ObjectBox> {
        match self {
            Object::Cons { car, cdr: _ } => Some(ObjectBox::new(car.as_ref())),
            _ => None,
        }
    }
}

Playground

  1. Clone what you need:
#[derive(Debug, Clone)]
pub enum Object {
    Integer(i64),
    Boolean(bool),
    Character(char),
    String(String),
    Symbol(String),
    Cons { car: Box<Object>, cdr: Box<Object> },
    Nil,
}

pub type ObjectBox = Box<Object>;

impl Object {
    pub fn car(&self) -> Option<ObjectBox> {
        match self {
            Object::Cons { car, cdr: _ } => Some(ObjectBox::new(*car.clone())),
            _ => None,
        }
    }
}

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM