`#[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=].
所以,目前(也许编译器将来会更聪明地处理这些情况),是的,这是您必须手动实施的情况之一。
似乎在派生 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=].
所以,目前(也许编译器将来会更聪明地处理这些情况),是的,这是您必须手动实施的情况之一。