Hi!
I'm learning Rust by working my way through Crafting Interpreters and have hit a stumbling block. Note, the language in the book is called Lox
which is why names below have Lox
prefix.
I have a trait, LoxCallable
which represents something (function, method on object, closure) which interpreter can call call()
on. This is one of the fields of an enum LoxObject
.
pub trait LoxCallable {
fn arity(&self) -> i32;
fn call(&mut self, interpreter: &mut Interpreter, arguments: &Vec<LoxObject>) -> InterpretResult<LoxObject>;
}
impl fmt::Debug for dyn LoxCallable {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<function arity {}>", self.arity())
}
}
impl fmt::Display for dyn LoxCallable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<function arity {}>", self.arity())
}
}
impl PartialEq<dyn LoxCallable> for dyn LoxCallable {
fn eq(&self, other: &Self) -> bool {
todo!();
//&self == &other
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum LoxObject {
Boolean(bool),
Callable(Rc<RefCell<dyn LoxCallable>>), // TROUBLE
Nil,
Number(f64),
Str(String),
Undefined,
}
I get the following error:
error[E0507]: cannot move out of `*__arg_1_0` which is behind a shared reference
--> src/interpreter.rs:58:14
|
58 | Callable(Rc<RefCell<dyn LoxCallable>>),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because `*__arg_1_0` has type `std::rc::Rc<std::cell::RefCell<dyn interpreter::LoxCallable>>`, which does not implement the `Copy` trait
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
As best I understand it, the problem here is that Rc<RefCell> doesn't have the Clone trait (thought I would have thought Rc::clone would give me that for "free").
If I get rid of the Clone
from LoxObject
this is fine, but I need clone elsewhere in the program.
Any thoughts on how to handle this? My thoughts are:
-
Don't make LoxCallable a Trait, make it a struct with the requisite methods and figure out later how to make it pseudo polymorphic later as needed.
-
Something with closures. But that's complex because these callables have a fair amount of state, eventually.