You cannot really clone trait objects. There’s the dyn_clone crate that could help with this. Depending on your concrete code / problem, there may also be other, easier solutions; feel free to provide some more details about the traits and functions involved.
The first question is why you are doing that. Usually you should accept general iterators or maybe just slices instead of fully-fledged collection types. If you make the function accept a slice instead, this problem will go away.
Anyway, to expand on @steffahn's answer, trait objects aren't cloneable because cloning requires the concrete type of the value being cloned to be known. A trait object only contains enough information to be able to stand in for an object that implements that specific trait, by storing a pointer to the opaque data and another to a vtable of method pointers to concrete methods, which in turn know how to handle the opaque data (since they were created from the specific underlying type at compile time).
A trait object is thus incapable of being cloned; that would require restoring the static type information, performing the clone, then downgrading it to a trait object again. The first of these steps is not really feasible or practical.
However, if your function is generic enough to at least accept a vector of any type that implements ToNumber, you could create a vector of references instead of a vector of boxed trait objects:
let vec_of_refs = slice_of_boxes
.iter()
.map(|x| &**x)
.collect::<Vec<&dyn ToNumber>>();
and then pass this vector to the function in question.
use dyn_clone::{clone_box, DynClone};
// add DynClone as supertrait
trait ToNumber: DynClone {
// methods here…
}
fn needs_vec(_arg: Vec<Box<dyn ToNumber>>) {
// implementation…
}
fn other_function(arg: &[Box<dyn ToNumber>]) {
// still can’t use `to_vec` directly
/*
needs_vec(arg.to_vec());
*/
// but this works
needs_vec(arg.iter().map(|x| clone_box(&**x)).collect());
// alternatively, you could add a `Clone` implementation for `Box<dyn ToNumber>`
// let’s do that for another trait ToNumber2 (see below), then we can do
let arg2: &[Box<dyn ToNumber2>] = &[];
let _vec: Vec<Box<dyn ToNumber2>> = arg2.to_vec();
// so if we did this for `ToNumber`, then
// `needs_vec(arg.to_vec());`
// would work, too.
}
trait ToNumber2: DynClone {
// methods here…
}
// the `+ '_` makes the impl a bit more general, otherwise we’d just
// cover Box<dyn ToNumber2 + 'static>, which is the desugared version of
// Box<dyn ToNumber2>
impl Clone for Box<dyn ToNumber2 + '_> {
fn clone(&self) -> Self {
clone_box(&**self)
}
}
This only works assuming the presence of some implementation impl<T: ?Sized> ToNumber for &T where T: ToNumber, otherwise Vec<&dyn ToNumber> isn’t “a vector of a type that implements ToNumber”.
I would try to refactor my code to use slices(or see if vector of references to trait objects would work for me) as @H2CO3 suggested, or fallback to dyn_clone crate as @steffahn suggested.
that have the slice of trait objects (the caller) / need the vec of trait objects (the callee).
In any case, your trait – only containing &self methods – does support an implementation like
impl<T: ?Sized> ToNumber for &T
where
T: ToNumber
{ … }
(and e.g. also for Box<T> / &mut T, I guess) so the option of generically taking a Vec<impl ToNumber> instead of Vec<Box<dyn ToNumber>> could indeed work. If it turns out that your method doesn’t need a Vec at all but can be implemented with slices, that’s even better, of course.
This also seem to have a ripple effect on all my enums which makes me introduce lifetimes everywhere. Since this seems like a lot of work, I will fallback to use dyn_clone crate. @steffahn
You could also consider using Rc<dyn ToNumber> instead of Box<dyn ToNumber>. Those can always be cloned, even without using the DynClone supertrait, and it’s cheaper if the underlying type implementing ToNumber has a nontrivial cost in order to be cloned.
OTOH, Rc don’t allow mutable access to the underlying value; but AFAICT, your ToNumber trait doesn't offer any way to mutate self anyway.
But if you do ever need mutable access, you could use Rc in a clone-on-write fashion, only cloning values if necessary, still saving cloning overhead in cases where you didn't need mutation
I also realised a hack that would have worked for me. I was serializing (Box, Vec<Box>) , I combined both of them into a collection and serialized to Json Array. The problem arose when I had to deserialize this, I could have tried to split the JsonArray at index 1, and then getting a Box and Vec<Box> separately from it. Or I could have change the serialization and deserialization format which didn't make me split anything. But the solutions suggested are better to move forward with.