Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy trait and PhantomData: Should this really move?

Tags:

rust

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?

like image 459
rlkw1024 Avatar asked Jul 12 '15 18:07

rlkw1024


1 Answers

I'd thought that deriving Copy for Val<Meters> would give Val<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> {}
like image 159
fjh Avatar answered Nov 16 '22 20:11

fjh