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:
the method
cloneexists but the following trait bounds were not satisfied: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.
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();
}
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.
来源:https://stackoverflow.com/questions/39415052/deriving-a-trait-results-in-unexpected-compiler-error-but-the-manual-implementa