本文介绍了派生特征会导致意外的编译器错误,但是手动实现有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码():

#[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 {
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^

使用添加使用std :: clone :: Clone; 不会更改任何内容,因为它已经处于序幕中。

Adding use std::clone::Clone; doesn't change anything, as it's already in the prelude anyway.

何时我删除了#[derive(Clone)] ,并为 Foo手动实现了 Clone ,它会按预期编译

When I remove the #[derive(Clone)] and manually implement Clone for Foo, it compiles as expected!

impl<'a, T> Clone for Foo<'a, T> {
    fn clone(&self) -> Self {
        Foo {
            t: self.t,
        }
    }
}

这是怎么回事?


  • #[derive()]之间是否有区别? -impls和手动工具?

  • 这是编译器错误吗?

  • 还有我没想到的东西吗?
  • Is there a difference between #[derive()]-impls and manual ones?
  • Is this a compiler bug?
  • Something else I didn't think of?

推荐答案

答案被隐藏在错误消息中:

The answer is buried in the error message:

    = 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 (以及许多其他自动派生的类型)时,它会添加克隆绑定到所有通用类型上。使用 rustc -Z不稳定选项--pretty = expanded ,我们可以看到它变成了:

When you derive Clone (and many other automatically-derived types), it adds a Clone bound on all generic types. Using rustc -Z unstable-options --pretty=expanded, we can see what it becomes:

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)),},
        }
    }
}

这种情况下,不需要绑定,因为通用类型在引用后面。

In this case, the bound is not needed because the generic type is behind a reference.

现在,您将需要自己实现 Clone 。 ,但这是一种相对罕见的解决方法

For now, you will need to implement Clone yourself. There's a Rust issue for this, but it's a comparatively rare case with a workaround.

这篇关于派生特征会导致意外的编译器错误,但是手动实现有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 09:34