Wierd behavior with associated items and Clone


#1

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!


#2

Looks like a known issue: https://github.com/rust-lang/rust/issues/26925


#3

Huh, okay.
Guess I’ll have to keep the manual Clone implementation then.