Why does rustc think GenericArray isn't copy?

Playground link.

use generic_array::{ArrayLength, GenericArray};

#[derive(Copy)]
pub struct Foo<N: ArrayLength<u64>>(GenericArray<u64, N>);

Gives the error:

error[E0204]: the trait `Copy` may not be implemented for this type
 --> src/lib.rs:3:10
  |
3 | #[derive(Copy)]
  |          ^^^^
4 | pub struct Foo<N: ArrayLength<u64> + Copy>(GenericArray<u64, N>);
  |                                            -------------------- this field does not implement `Copy`

But the docs for GenericArray say it does implement Copy as long as T does. In this case T=u64 which definitely does. What am I missing?

If you read more closely, you’ll see that the docs for GenericArray speficy that you also need N::ArrayType: Copy. Hence

#[derive(Clone, Copy)]
pub struct Foo<N: ArrayLength<u64>>(GenericArray<u64, N>)
where
    N::ArrayType: Copy;

does work.

You can also move the N::ArrayType: Copy bound to the Copy implementation to spare you the need to repeat it everywhere else when handling the Foo type. In this case you can’t use derive for Copy anymore, but it’s not too much overhead:

#[derive(Clone)]
pub struct Foo<N: ArrayLength<u64>>(GenericArray<u64, N>);
impl<N: ArrayLength<u64>> Copy for Foo<N> where N::ArrayType: Copy {}
1 Like

I see so the problem is the compiler doesn't know that all types that satisfy ArrayLength<u64> result in N::ArrayType: Copy? Which just going based on the definition of ArrayLength I can see why it would not since there is no trait bound put on ArrayType.

1 Like

Well, “all types that satisfy ArrayLength<u64>” is actually an open set of types. Anyone can add additional implementations in a way that the corresponding ArrayType is not Copy. Realistically youʼre probably only ever going to use the implementations for the typenum-types that come with the generic-array crate itself, and all those do ensure that N::ArrayType: Copy is satisfied. But thereʼs no way the compiler can know that youʼre only intending or use those well-behaved implementations when you donʼt add that N::ArrayType: Copy constraint.

1 Like