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?
#[derive()]
-impls and manual ones?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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With