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: no method named `clone` found for type `Foo<'a, T>` in the current scope
--> <anon>:7:9
|>
16 |> foo.clone();
|> ^^^^^
note: the method `clone` exists but the following trait bounds were not satisfied: `T : std::clone::Clone`
help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `clone`, perhaps you need to implement it:
help: candidate #1: `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?
The answer is buried in the error message:
When you derive
Clone
(and many other automatically-derived types), it adds aClone
bound on all generic types. Usingrustc -Z unstable-options --pretty=expanded
, we can see what it becomes: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.Your example will derive
Clone
without any problems if you explicitly mark thatT
should implementClone
, like this:(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.