Why references to trait objects are not cloneable? This code compiles:
struct Test;
fn clone_vec<'a>(v: Vec<&'a Test>) -> Vec<&'a Test> {
v.clone()
}
fn main() {
}
This one doesn't:
trait Test {
fn do_smt(&self);
}
fn clone_vec<'a>(v: Vec<&'a Test>) -> Vec<&'a Test> {
v.clone()
}
fn main() {
}
Error:
main3.rs:7:5: 7:14 error: failed to find an implementation of trait std::clone::Clone for &'a Test<no-bounds>
main3.rs:7 v.clone()
^~~~~~~~~
However, Clone
trait is implemented for any kind of reference, as far as I can see:
impl<'a, T> Clone for &'a T {
/// Return a shallow copy of the reference.
#[inline]
fn clone(&self) -> &'a T { *self }
}
I just don't see why &'a Test
where Test
is a trait is not cloneable. It's just a pointer after all. This restriction prohibits, for example, going from &[&'a SomeTrait]
to Vec<&'a SomeTrait>
, which looks like an obvious conversion, or cloning a Vec<&'a SomeTrait>
, as in the example.
This is very strange provided that I can implement clone_vec()
myself, without Clone
:
fn clone_vec<'a>(v: Vec<&'a Test>) -> Vec<&'a Test> {
let mut result = Vec::new();
for &e in v.iter() {
result.push(e);
}
result
}
Clone
is a normal library trait, and requires normal (library) implementations, for all types. For example, Clone
is implemented for &T
right here, in the form:
impl<'a, T> Clone for &'a T {
/// Return a shallow copy of the reference.
#[inline]
fn clone(&self) -> &'a T { *self }
}
Hence, everything of the form &T
is Clone
able... where T
a concrete type. And that's the clincher: &Trait
is not (yet) a type of the form &T
with T = Trait
(but rather an "atomic"/primitive type that can't be separated into parts), so it is not covered by that impl
.
We require dynamically sized types (DST) for the compiler to be able to reason about passing just plain old Trait
around as a generic parameter (Nick Cameron is actually hard at work at some parts of the DST implementation, so this will hopefully happen soon).
You can, however, manually implement Clone
for your traits of interest, e.g. the following works well:
trait Foo {}
impl<'a> Clone for &'a Foo {
fn clone(&self) -> &'a Foo {
*self
}
}
However, it only works for traits defined in your current crate, or else the compiler has concerns about coherence (e.g. changing Foo
to Eq
in the impl
above causes error: cannot provide an extension implementation where both trait and type are not defined in this crate
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With