这段代码(playground):
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T>(foo: Foo<'a, T>) {
foo.clone();
}
......不编译:
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`
无论如何,添加 use std::clone::Clone;
不是't change anything, as it'已经在前奏中了 .
当我删除 #[derive(Clone)]
并为 Foo
手动实现 Clone
时,它 compiles as expected !
impl<'a, T> Clone for Foo<'a, T> {
fn clone(&self) -> Self {
Foo {
t: self.t,
}
}
}
这里发生了什么?
-
#[derive()]
-impls与手动之间有区别吗? -
这是编译器错误吗?
-
我没想到的其他东西?
2 回答
答案隐藏在错误消息中:
当您派生
Clone
(以及许多其他自动派生类型)时,它会在 all 泛型类型上添加Clone
绑定 . 使用rustc -Z unstable-options --pretty=expanded
,我们可以看到它变成了什么:在这种情况下,不需要绑定,因为泛型类型在引用后面 .
目前,您需要自己实施
Clone
. There's a Rust issue for this,但这是一个相对罕见的解决方案 .如果您明确标记
T
应该实现Clone
,那么您的示例将派生Clone
没有任何问题,如下所示:(Playground link)
你可以避免明确地指定绑定似乎很不寻常,但Shepmaster的答案似乎暗示编译器隐式插入它,所以我的建议在功能上是相同的 .