Switching from Box<T> to Rc<T> for a Scheme-like Cons list doesn't compile

109 views Asked by At

The program below compiles and runs if Rc is replaced with Box. Why doesn't it compile when using reference counting? This is a question about the difference between Rc<T> and Box<T>.

use std::rc::Rc;

#[derive(Debug, Clone)]
pub enum ILst {
    Nil,
    Cons(i32, Rc<ILst>),
}

impl ILst {
    pub fn new() -> Self {
        ILst::Nil
    }

    pub fn cons(self, item: i32) -> Self {
        ILst::Cons(item, Rc::new(self)) 
    }

    pub fn car(&self) -> Option<i32> {
        match *self {
            ILst::Cons(u, ref _v) => Some(u),
            ILst::Nil => None,
        }
    }

    pub fn cdr(&self) -> Self {
        match *self {
            ILst::Cons(_u, ref v) => *v.clone(),
            ILst::Nil => ILst::Nil,
        }
    }
}

fn main() {
    let list = ILst::new().cons(17).cons(29);
    let rest = list.cdr();
    println!("list  = {:?}", rest);
}
error[E0507]: cannot move out of borrowed content
  --> src/main.rs:27:38
   |
27 |             ILst::Cons(_u, ref v) => *v.clone(),
   |                                      ^^^^^^^^^^ cannot move out of borrowed content
1

There are 1 answers

4
Anthony Maida On

The solution seems to be to replace

*v.clone()

with

Rc::deref(v).clone()

and then add the line

use::ops::Deref;

to the beginning of the program.