How to clone a struct with Option<Box<dyn Any>>

I have a struct similar to this

#[derive(Debug, Clone)]
pub struct Token {
    pub lexeme: String,
    pub value: Option<Box<dyn Any>>,
    pub line: u32,
}

Adding the #[derive(Clone)] part leads to the compilation error:

error[E0277]: the trait bound `dyn std::any::Any: Clone` is not satisfied
  --> src/token.rs:85:5
   |
81 | #[derive(Debug, Clone)]
   |                 ----- in this derive macro expansion
...
85 |     pub value: Option<Box<dyn Any>>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `dyn std::any::Any`
   |
   = note: required for `Box<dyn std::any::Any>` to implement `Clone`
   = note: 1 redundant requirement hidden
   = note: required for `Option<Box<dyn std::any::Any>>` to implement `Clone`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)

It seems the issue is Any does not implement Clone which kinda makes sense since Any means any type.

The question now is, with such a data structure, how would one go about using it in cases where it values needs to be clones or copied?

If you actually want to clone the underlying type in the box, then using the dyn_clone - Rust crate can be an option. To re-gain Any-like functionality on a different trait than Any itself, you can use the downcast - Rust crate. Together this could be something like

/*
[dependencies]
dyn-clone = "1"
downcast = "0.11"
*/

use dyn_clone::{clone_trait_object, DynClone};
use downcast::{Any, downcast};

use std::fmt;

pub trait Value: DynClone + Any {}
clone_trait_object!(Value);
downcast!(dyn Value);

impl<T: Clone + Any> Value for T {}

impl fmt::Debug for dyn Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Value").finish_non_exhaustive()
    }
}

#[derive(Debug, Clone)]
pub struct Token {
    pub lexeme: String,
    pub value: Option<Box<dyn Value>>,
    pub line: u32,
}

If you only need read-only access to the value anyways, then the alternative of simply using Option<Rc<dyn Any>> could be better, i.e. simpler to code and also more efficient, as cloning an Rc will be cheaper.

4 Likes

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.