How does the compiler check the implementation of the Copy trait for a type?

For example, there is
let array: &[i32; 0];
How does the compiler check the implementation of the Copy trait for a type?
Will the compiler look at the value type i32 or at the entire &[i32; 0] to understand whether to copy data or move ?
It turns out that if the Copy trait is implemented for the i32 type, then it is not necessarily implemented for the [i32;_] or &[i32;_] or &mut [i32;_]?

The implementation bounds are listed in the stdlib documentation:

5 Likes

For nominal structs, you have to opt-in by implementing Clone and Copy. Moreover, you can only opt-in to Copy if all your fields are also Copy. Additionally, any type that has a non-trivial destructor (implements Drop or contains a type that implements Drop) cannot be Copy.

You can consider these to be recursive requirements. What are the base cases of the requirements? Built-in and compiler-defined types.

Many are always Copy...

  • The built-in integer and float types
  • bool and char
  • Raw pointers (*const T, *mut T), regardless of T
  • Shared references (&T), regardless of T
  • PhantomData<T> and friends, regardless of T
  • Function item types and function pointers (fn(Arg) -> Out), regardless of arguments or output type

...some are conditionally Copy...

  • [T; N] if and only if T: Copy
  • (T0, T1, ..., TN) if and only if all of T0, ..., TN are also Copy (this includes ())
  • Closures, if all their captures are Copy

...and some are never Copy.

  • Exclusive references (&mut T), regardless of T
  • Unsized types
    • [T], regardless of T
    • str
    • dyn Trait
  • Any "magic" std type that allocates or otherwise drops
    • In particular, Box<T>, regardless of T
3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.