On my latest project, while working with associated items, I have stumbled upon a behavior which seems non-intuitive. Take this code (playground):
trait MarkerTrait {
type Foo: Clone;
type Bar: Clone;
type Baz: Clone;
}
#[derive(Clone)]
struct Thing<T: MarkerTrait> {
foo: T::Foo,
bar: T::Bar,
baz: T::Baz
}
In it, I use the MarkerTrait
to regroup several types together via associated items. Then, the Thing
type use the MarkerTrait
to determine the type of its members. Note that a Thing
doesn't actually contains a MarkerTrait
; it only uses its associated types. I expect that Thing<T>
will implement Clone
whenever T::Foo
, T::Bar
and T::Baz
do.
Now, let's use our types:
struct MarkerStruct;
impl MarkerTrait for MarkerStruct {
type Foo = u32;
type Bar = String;
type Baz = f64;
}
fn main() {
let thing = Thing::<MarkerStruct> {
foo: 42,
bar: "hello".to_owned(),
baz: 3.14
};
let cloned = thing.clone();
}
Unfortunately, this doesn't compile, and I have to add a #[derive(Clone)]
to MarkerStruct
manually.
Interestingly, if I implement Clone
manually (playground) like this:
impl<T: MarkerTrait> Clone for Thing<T> where
T::Foo: Clone,
T::Bar: Clone,
T::Baz: Clone {
fn clone(&self) -> Self {
Thing {
foo: self.foo.clone(),
bar: self.bar.clone(),
baz: self.baz.clone()
}
}
}
The code compiles just fine, which suggests a bug in the implementation of #[derive(Clone)]
.
Is there another way to bypass that issue?
Thanks!