Theme
Q021. When can a type implement Copy?
Short Answer
A type can implement Copy only when all data it contains is also Copy and the type does not implement Drop. Every field of a struct and every payload of an enum must satisfy that requirement. Eligibility is not automatic: the type author chooses whether implicit duplication is appropriate and stable as part of the public API.
Deep Dive
Common Copy types include numeric primitives, bool, char, shared references, raw pointers, and function pointers. Composite types are eligible only when their contents are Copy:
[T; N]isCopywhenT: Copy;- tuples are
Copywhen every element isCopy; Option<T>isCopywhenT: Copy;- a user-defined struct or enum must explicitly implement or derive
Copy.
String, Vec<T>, Box<T>, Rc<T>, Arc<T>, and owning OS handles are not Copy. Mutable references are also not Copy, because implicit duplication would violate their exclusive-access contract.
Even an eligible type may intentionally remain non-Copy to preserve unique capability semantics, avoid accidental large copies, or retain the option to add non-Copy fields later. Adding or removing Copy can affect downstream code and is an API design decision.
Internal Model
The compiler verifies structural eligibility. #[derive(Copy)] also derives bounds for generic parameters based on the generated implementation, often requiring T: Copy when a field contains T.
Copy has Clone as a supertrait, so a type must implement both. The usual declaration is #[derive(Clone, Copy)]; writing a manual implementation cannot bypass non-Copy fields or a Drop implementation.
Example
rust
#[derive(Clone, Copy)]
struct UserId(u64);
fn require_copy<T: Copy>(_: T) {}
fn main() {
let first = UserId(42);
let second = first;
require_copy(first);
println!("{} {}", first.0, second.0);
// String does not satisfy the Copy bound:
// require_copy(String::from("Alice"));
}Common Mistakes
- Assuming a struct automatically becomes
Copywhen all fields areCopy. - Thinking only primitive types can implement
Copy. - Treating
Copypurely as a performance annotation rather than an API semantic promise.
Follow-ups
- Why is implementing
Copya public API commitment? - How does deriving
Copyaffect generic bounds? - Why is
&mut Tnon-Copyeven whenT: Copy?
Related
- Q019. How does
Copychange assignment and move semantics? - Q020. What is the difference between
CopyandClone? - Q022. Why can a type that implements
Dropnot implementCopy?
References
- The Rust Programming Language
- Rust Reference
- Rust API Guidelines