PhantomData
interacts with Copy
in a surprising way:
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;
}
This fails as follows:
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;
I'd thought that deriving Copy
for Val<Meters>
would give Val<Meters>
copy semantics. But apparently, that's true only where Val
's type parameter T
also implements Copy
. I don't understand why.
PhantomData
always implements Copy
, regardless of whether its type parameter does. And anyhow, if PhantomData<Meters>
didn't implement Copy
, I'd expect the compiler to complain that it couldn't derive Copy
for Val<Meters>
. Instead, the compiler happily derives Copy
for Val<Meters>
, yet it applies move semantics.
Is this behavior intentional? If so, why?
I'd thought that deriving Copy for
Val<Meters>
would giveVal<Meters>
copy semantics.
But Copy
isn't being derived for Val<Meters>
, just for all Val<T>
where T
itself is Copy
.
There are several open issues on Github for this, e.g. this one. My impression is that this is not intentional, but just a limitation of the way derive
currently works.
You can work around this by manually writing a blanket impl for Clone
and Copy
:
impl <T> Clone for Val<T> {
fn clone(&self) -> Val<T> {
Val {v: PhantomData}
}
}
impl <T> Copy for Val<T> {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With