19

This code (playground):

#[derive(Clone)]
struct Foo<'a, T: 'a> {
    t: &'a T,
}

fn bar<'a, T>(foo: Foo<'a, T>) {
    foo.clone();
}

... does not compile:

error[E0599]: no method named `clone` found for struct `Foo<'a, T>` in the current scope
   --> src/main.rs:16:9
    |
3   | struct Foo<'a, T: 'a> {
    | ---------------------
    | |
    | method `clone` not found for this
    | doesn't satisfy `Foo<'_, T>: std::clone::Clone`
...
16  |     foo.clone();
    |         ^^^^^ method not found in `Foo<'a, T>`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
            `T: std::clone::Clone`
            which is required by `Foo<'_, T>: std::clone::Clone`
help: consider restricting the type parameter to satisfy the trait bound
    |
3   | struct Foo<'a, T: 'a> where T: std::clone::Clone {
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^

Adding use std::clone::Clone; doesn't change anything, as it's already in the prelude anyway.

When I remove the #[derive(Clone)] and manually implement Clone for Foo, it compiles as expected!

impl<'a, T> Clone for Foo<'a, T> {
    fn clone(&self) -> Self {
        Foo {
            t: self.t,
        }
    }
}

What is going on here?

  • Is there a difference between #[derive()]-impls and manual ones?
  • Is this a compiler bug?
  • Something else I didn't think of?
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Lukas Kalbertodt
  • 79,749
  • 26
  • 255
  • 305

2 Answers2

31

The answer is buried in the error message:

    = note: the method `clone` exists but the following trait bounds were not satisfied:
            `T: std::clone::Clone`
            which is required by `Foo<'_, T>: std::clone::Clone`

When you derive Clone (and many other automatically-derived types), it adds a Clone bound on all generic types. Using rustc -Z unstable-options --pretty=expanded, we can see what it becomes:

impl <'a, T: ::std::clone::Clone + 'a> ::std::clone::Clone for Foo<'a, T> {
    #[inline]
    fn clone(&self) -> Foo<'a, T> {
        match *self {
            Foo { t: ref __self_0_0 } =>
            Foo{t: ::std::clone::Clone::clone(&(*__self_0_0)),},
        }
    }
}

In this case, the bound is not needed because the generic type is behind a reference.

For now, you will need to implement Clone yourself. There's a Rust issue for this, but it's a comparatively rare case with a workaround.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
4

Your example will derive Clone without any problems if you explicitly mark that T should implement Clone, like this:

#[derive(Clone)]
struct Foo<'a, T: 'a> {
    t: &'a T,
}

fn bar<'a, T: Clone>(foo: Foo<'a, T>) {
    foo.clone();
}

(Playground link)

It seems unusual that you can avoid specifying the bound explicitly, but Shepmaster's answer seems to suggest that the compiler inserts it implicitly, so my suggestion is functionally identical.

Aurora0001
  • 13,139
  • 5
  • 50
  • 53
  • 1
    This is a good solution, but I disagree with *functionally identical* — in this case, the struct can only contain a `T` that implements `Clone`, but that particular bound isn't **required** to clone a reference. If the program requires `T` to be cloned for other reasons, this works. – Shepmaster Sep 09 '16 at 15:55
  • Oh, I assumed that `T: ::std::clone::Clone + 'a` from your example meant that `T` implemented `Clone` anyway; am I misunderstanding? – Aurora0001 Sep 09 '16 at 15:56
  • @Shepmaster, after some testing I've found that you can remove the `Clone` bound on `T` in the struct without problems, and by doing that I produce exactly the same output from the expanded pretty printer as the manual `impl`. – Aurora0001 Sep 09 '16 at 16:14
  • No, that's my fault for being unclear. I meant that my "solution" is to implement `Clone` without deriving it. That allows the structure to not have the restriction at all. – Shepmaster Sep 09 '16 at 16:14