首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >派生一个特性会导致意外的编译器错误,但是手动实现可以工作。

派生一个特性会导致意外的编译器错误,但是手动实现可以工作。
EN

Stack Overflow用户
提问于 2016-09-09 15:29:56
回答 2查看 2.4K关注 0票数 18

此代码(游乐场):

代码语言:javascript
运行
复制
#[derive(Clone)]
struct Foo<'a, T: 'a> {
    t: &'a T,
}

fn bar<'a, T>(foo: Foo<'a, T>) {
    foo.clone();
}

..。不编译:

代码语言:javascript
运行
复制
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时,会按预期的编译!

代码语言:javascript
运行
复制
impl<'a, T> Clone for Foo<'a, T> {
    fn clone(&self) -> Self {
        Foo {
            t: self.t,
        }
    }
}

这里发生什么事情?

  • #[derive()]-impls和手动-impls有什么区别吗?
  • 这是编译器的错误吗?
  • 还有什么我没想过的?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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,我们可以看到它变成了什么:

代码语言:javascript
运行
复制
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这有个锈蚀的问题,但这是一个比较少见的解决方案。

票数 28
EN

Stack Overflow用户

发布于 2016-09-09 15:52:02

如果显式地标记T应该实现Clone,则示例将没有任何问题地派生Clone,如下所示:

代码语言:javascript
运行
复制
#[derive(Clone)]
struct Foo<'a, T: 'a> {
    t: &'a T,
}

fn bar<'a, T: Clone>(foo: Foo<'a, T>) {
    foo.clone();
}

(操场链接)

避免显式指定绑定似乎很不寻常,但Shepmaster的回答似乎表明编译器隐式插入绑定,因此我的建议在功能上是相同的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39415052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档