`#[derive(Clone)]` 似乎错误地将泛型强制为 `Clone`

Fin*_*nis 8 generics rust

似乎在派生时Clone,Rust 将Clone特征要求转发给不需要该特征的泛型,就像它们被包装在Arc.

我是否误解了Clone工作原理或者这是编译器错误?

考虑以下代码,其中a.clone()可行,但b.clone()不可行。另请注意,如果没有b.clone()调用,代码可以正常编译,表明可以#[derive(Clone)]正常工作。

use std::sync::Arc;

struct Unclonable {}

struct A<T>(Arc<T>);
impl<T> Clone for A<T> {
    fn clone(&self) -> Self {
        Self(self.0.clone())
    }
}

#[derive(Clone)]
struct B<T>(Arc<T>);

fn main() {
    let a = A(Arc::new(Unclonable {}));
    let b = B(Arc::new(Unclonable {}));

    // Works
    a.clone();
    // Fails
    b.clone();
}
Run Code Online (Sandbox Code Playgroud)
   |
3  | struct Unclonable {}
   | ----------------- doesn't satisfy `Unclonable: Clone`
...
13 | struct B<T>(Arc<T>);
   | --------------------
   | |
   | method `clone` not found for this
   | doesn't satisfy `B<Unclonable>: Clone`
...
22 |     b.clone();
   |       ^^^^^ method cannot be called on `B<Unclonable>` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `Unclonable: Clone`
           which is required by `B<Unclonable>: Clone`
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `clone`, perhaps you need to implement it:
           candidate #1: `Clone`
help: consider annotating `Unclonable` with `#[derive(Clone)]`
   |
3  | #[derive(Clone)]
   |
Run Code Online (Sandbox Code Playgroud)

当我展开宏时,我看到以下生成的代码:

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2018::*;
#[macro_use]
extern crate std;
use std::sync::Arc;
struct Unclonable {}
struct A<T>(Arc<T>);
impl<T> Clone for A<T> {
    fn clone(&self) -> Self {
        Self(self.0.clone())
    }
}
struct B<T>(Arc<T>);
#[automatically_derived]
#[allow(unused_qualifications)]
impl<T: ::core::clone::Clone> ::core::clone::Clone for B<T> {
    #[inline]
    fn clone(&self) -> B<T> {
        match *self {
            B(ref __self_0_0) => B(::core::clone::Clone::clone(&(*__self_0_0))),
        }
    }
}
fn main() {
    let a = A(Arc::new(Unclonable {}));
    let b = B(Arc::new(Unclonable {}));
    a.clone();
    b.clone();
}
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事?为什么 Rust 编译器会添加<T: ::core::clone::Clone>??

或者这只是预期方式是手动实施的情况之一Clone

Bla*_*ans 9

从某种意义上说,这不是一个编译器错误,它是一种记录在案的行为,尽管人们可能会觉得它很奇怪。编译器在派生时会自动向泛型类型添加约束,即使这些约束在实现中实际上并不需要。例如,派生CloneforB<T>只会实现Clone for B<T>where ,尽管无论是否is 都T: Clone可能实现它。TClone

所以,就目前而言(也许编译器将来会对这些情况变得更聪明),是的,这是您必须手动实现的情况之一。