PhantomData
与Copy
以令人惊讶的方式进行交互:复制特质和PhantomData:这个真的应该移动吗?
use std::marker::PhantomData;
#[derive(Copy, Clone)]
pub struct Seconds;
pub struct Meters;
#[derive(Copy, Clone)]
pub struct Val<T> {
pub v: PhantomData<T>
}
fn main() {
let v1: Val<Seconds> = Val {v: PhantomData};
let v2 = v1;
let v3 = v1;
let v4: Val<Meters> = Val {v: PhantomData};
let v5 = v4;
let v6 = v4;
}
这失败如下:
src/main.rs:20:13: 20:15 error: use of moved value: `v4` [E0382]
src/main.rs:20 let v6 = v4;
^~
src/main.rs:19:13: 19:15 note: `v4` moved here because it has type `Val<Meters>`, which is moved by default
src/main.rs:19 let v5 = v4;
我还以为,对于Val<Meters>
获得Copy
会给Val<Meters>
复制语义。但显然,只有在Val
的类型参数T
也实现了Copy
时,才是如此。我不明白为什么。
PhantomData
总是执行Copy
,regardless of whether its type parameter does。无论如何,如果PhantomData<Meters>
没有实现Copy
,我希望编译器抱怨它不能派生Copy
Val<Meters>
。相反,编译器为Val<Meters>
愉快地派生Copy
,但它适用移动语义。
这种行为是故意的吗?如果是这样,为什么?
我有同样的印象很好,因为据我所知'仿制药使用derive'只尝试实施性状是基于通用参数本身是否已经实现它。我怀疑潜在的问题是,决定实现这个特征是否可行实际上是相当复杂的,因此它现在只是尽力而为;请注意,当'derive'失败时,您可以轻松移动到手动实现。 –
这是令人惊讶的:所有'Val'字段都保证实现'Copy',而不管'T'的类型如何,因为'PhantomData'总是实现'Copy'。同样奇怪的是(但与你的评论一致)是因为编译器不能保证'T'实现'Copy',所以''''''''''''''''''''''''''''''''''''''''''看起来这应该不重要:[docs](http://doc.rust-lang.org/std/marker/trait.Copy.html)表示“一个类型可以实现'Copy',如果它的全部组件实现'Copy'。“文档没有说所有的*类型参数都必须实现'Copy'。 – rlkw1024
@ rlkw1024是的,整个情况并不理想。整个标准库中都有类似[this one](https://github.com/rust-lang/rust/blob/master/src/libcollections/linked_list.rs#L66)的fixms。我不确定这是否是一个实际的问题,但我已经更新了我的答案,以显示如何为您的类型手动实现'Copy'。 – fjh