此代码(playground):
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T>(foo: Foo<'a, T>) {
foo.clone();
}
...无法编译: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 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
添加use std::clone::Clone;
不会改变任何内容,因为它已经在序幕中了。当我删除
#[derive(Clone)]
并手动为Clone
实现Foo
时,它会按预期的方式编译!impl<'a, T> Clone for Foo<'a, T> {
fn clone(&self) -> Self {
Foo {
t: self.t,
}
}
}
这里发生了什么?#[derive()]
-impls和手动的有什么区别吗? 最佳答案
答案隐藏在错误消息中:
派生Clone
(以及许多其他自动派生的类型)时,它会在所有泛型类型上添加一个Clone
。使用rustc -Z unstable-options --pretty=expanded
,我们可以看到它变成了什么:
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)),},
}
}
}
在这种情况下,不需要边界,因为泛型类型在引用后面。现在,您将需要自己实现
Clone
。 There's a Rust issue for this,但这是一种相对罕见的解决方法。