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

`#[derive(Clone)]` seems to wrongfully enforce generic to be `clone`

似乎在派生 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();
}
   |
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)]
   |

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

#![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();
}

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

或者这只是其中一种情况,其中预期的方法是手动实施 Clone

从某种意义上说,这不是一个编译器错误,它是一个 documented behavior,尽管人们可能会觉得它很奇怪。编译器会在派生时自动为泛型类型添加约束,即使在实现中实际上并不需要这些约束。例如,为 B<T> 派生 Clone 将仅在 T: Clone 处实现 Clone for B<T>,尽管无论 T 是否为 [=] 都可能实现它10=].

所以,目前(也许编译器将来会更聪明地处理这些情况),是的,这是您必须手动实施的情况之一。