此代码(游乐场):
#[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)]
并手动为Foo
实现Clone
时,会按预期的编译!
impl<'a, T> Clone for Foo<'a, T> {
fn clone(&self) -> Self {
Foo {
t: self.t,
}
}
}
这里发生什么事情?
#[derive()]
-impls和手动-impls有什么区别吗?发布于 2016-09-09 15:40:51
答案隐藏在错误信息中:
= 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`
当您派生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
。这有个锈蚀的问题,但这是一个比较少见的解决方案。
发布于 2016-09-09 15:52:02
如果显式地标记T
应该实现Clone
,则示例将没有任何问题地派生Clone
,如下所示:
#[derive(Clone)]
struct Foo<'a, T: 'a> {
t: &'a T,
}
fn bar<'a, T: Clone>(foo: Foo<'a, T>) {
foo.clone();
}
(操场链接)
避免显式指定绑定似乎很不寻常,但Shepmaster的回答似乎表明编译器隐式插入绑定,因此我的建议在功能上是相同的。
https://stackoverflow.com/questions/39415052
复制相似问题