Trait bound dyn Fn: Clone is not satisifed

Hi,
I have an enum which looks like this,

#[derive(Debug, Clone, PartialEq)]
pub enum Object {
    Integer(i64),
    String(String),
    Boolean(bool),
    ReturnValue(Box<Object>),
    Error(String),
    Function(Function),
    Builtin(BuiltinFunction),
    Null,
}

BuiltinFunction looks like this,

type Builtin = dyn Fn(Object) -> Object;
#[derive(Clone)]
pub struct BuiltinFunction {
    func: Box<Builtin>,
}
impl fmt::Debug for BuiltinFunction {
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
        f.debug_struct("BuiltinFunction")
            .field("func", &"builtin")
            .finish()
    }
}
impl PartialEq for BuiltinFunction {
    fn eq(&self, _: &Self) -> bool {
        false
    }
}

I am getting this error that I do not know how to fix,

error[E0277]: the trait bound `dyn Fn(Object) -> Object: Clone` is not satisfied
   --> src/evaluator/mod.rs:123:5
    |
121 | #[derive(Clone)]
    |          ----- in this derive macro expansion
122 | pub struct BuiltinFunction {
123 |     func: Box<Builtin>,
    |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `dyn Fn(Object) -> Object`, which is required by `Box<dyn Fn(Object) -> Object>: Clone`
    |
    = note: required for `Box<dyn Fn(Object) -> Object>` to implement `Clone`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use parentheses to call this trait object
    |
123 |     func: Box<Builtin>(/* Object */),
    |                       ++++++++++++++

I can not remove derive Clone from Object enum because it's used in other places in the code and has to be implemented. I sort of understand this error but I have no idea how to fix it.

There are a few ways, each with its own drawbacks. The simplest is probably to replace Box<Builtin> with Rc<Builtin> which will make it cloneable. But if the closure contains any captures with internal mutability, the clones will see each other's changes which may not be what you want.

If there will never be any captures, you can use a function pointer instead of a trait object:

type Builtin = fn(Object)->Object;

#[derive(Copy,Clone)]
pub struct BuiltinFunction {
    func: Builtin,
}

// ...
4 Likes

This will be a pure function with no captured values so both solutions will be okay for me.
I changed it to use function pointer from the trait object. Thank you!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.