Tuple is not a type?

compile the code

struct StreamWrapper<F, T, U>(F, PhantomData<(T, U)>)

get:

rustc [E0277]: the trait bound U: std::marker::Copy is not satisfied
the trait std::marker::Copy is not implemented for U
rustc [E0277]: the trait bound T: std::marker::Copy is not satisfied
the trait std::marker::Copy is not implemented for T

but still, there is

impl<T> Copy for PhantomData<T>
where
    T: ?Sized,

in std library,

So, tuple is not a type?

You might want to provide a full example that shows this error.
The single line of code that you provided does not.

3 Likes

You'll need to bound the generic type parameters T and U to implement the Copy trait.

Not necessary. PhantomData has an impl of the Copy trait with no bounds on the type of <T> .

Tuples and types have nothing do with it. If you're #[derive(Clone, Copy)]-ing your StreamWrapper by the time your code is about to compile it will expand to:

struct StreamWrapper<F, T, U>(F, PhantomData<(T, U)>);
// for #[derive(Copy)]
impl<F: Copy, T: Copy, U: Copy> Copy for StreamWrapper<F, T, U> {}
// for #[derive(Clone)]
impl<F: Clone, T: Clone, U: Clone> Clone for StreamWrapper<F, T, U> {
    fn clone(&self) -> Self {
        Self(self.0.clone(), self.1.clone())
    }
}

Which is clearly not what you want. impl both Clone and Copy yourself instead:

impl<F: Copy, T, U> Copy 
for StreamWrapper<F, T, U> {}

impl<F: Clone, T, U> Clone 
for StreamWrapper<F, T, U> {
    fn clone(&self) -> Self {
        Self(self.0.clone(), PhantomData)
    }
}
7 Likes

It's a naive question, but does that differ much? self.1.clone() will use PhantomData's implementation of Clone, which simply returns a Self.

It's not implementation that is different (it indeed is effectively the same). It's the bounds. derive always restricts all generic parameters, no matter how exactly are they used.

4 Likes

Thanks. Indeed, I misread the expanded code and I completely missed that part.