此代码(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)),},
            }
        }
    }
    
    在这种情况下,不需要边界,因为泛型类型在引用后面。
    现在,您将需要自己实现CloneThere's a Rust issue for this,但这是一种相对罕见的解决方法。

    09-04 04:56
    查看更多