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