The Copy Trait
The Copy trait (std::marker::Copy) is a special compiler marker trait with no methods. Implementing Copy for a custom struct or enum opts that type out of move semantics and tells rustc to duplicate values implicitly using a shallow bitwise stack copy (memcpy) whenever a value is assigned or passed by value.
Definition of Copy (pub trait Copy: Clone {})
In the standard library, Copy is a subtrait of Clone:
pub trait Copy: Clone {
// Empty marker trait — no methods to implement!
}
Because Copy requires Clone as a supertrait, every type that implements Copy must also implement Clone. The easiest and most idiomatic way to implement both on a custom struct or enum is via #[derive(Clone, Copy)]:
#[derive(Debug, Clone, Copy, PartialEq)]
struct Point {
x: i32,
y: i32,
}
fn translate(mut p: Point, dx: i32, dy: i32) -> Point {
p.x += dx;
p.y += dy;
p
}
fn main() {
let origin = Point { x: 0, y: 0 };
// Because `Point` derives `Copy`, `origin` is copied into `translate`, NOT moved!
let shifted = translate(origin, 10, -5);
println!("origin: {origin:?}");
println!("shifted: {shifted:?}");
}
origin: Point { x: 0, y: 0 }
shifted: Point { x: 10, y: -5 }
Two Strict Compiler Requirements for Implementing Copy
Not every custom type is allowed to implement Copy. The compiler enforces two hard rules:
| Rule | Error Code on Violation | Why the Rule Exists |
|---|---|---|
1. Every field/variant must itself implement Copy |
E0204 |
If any field owns heap memory (such as String or Vec<T>), a bitwise stack copy would alias that heap pointer and cause a double free |
2. The type cannot implement Drop (Copy and Drop are mutually exclusive!) |
E0184 |
If a type needs custom cleanup logic in Drop::drop, duplicating its bits implicitly without running a constructor would run Drop multiple times on the same resource |
Error When a Field Is Not Copy (E0204)
// ❌ does not compile
#[derive(Clone, Copy)]
struct UserBadge {
id: u32,
label: String, // `String` does not implement `Copy`!
}
fn main() {}
error[E0204]: the trait `Copy` cannot be implemented for this type
--> src/main.rs:2:17
|
2 | #[derive(Clone, Copy)]
| ^^^^
...
5 | label: String,
| ------------- this field does not implement `Copy`
error: aborting due to 1 previous error
Error When Combining Copy and Drop (E0184)
// ❌ does not compile
#[derive(Clone, Copy)]
struct FileDescriptor(i32);
impl Drop for FileDescriptor {
fn drop(&mut self) {}
}
fn main() {}
error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor
--> src/main.rs:2:17
|
2 | #[derive(Clone, Copy)]
| ^^^^ `Copy` not allowed on types with destructors
error: aborting due to 1 previous error
When Should Your Custom Type Derive Copy?
Even if all fields of a struct are Copy, custom structs and enums are not Copy by default—you must opt in explicitly with #[derive(Clone, Copy)]:
- Do implement
Copyfor small, pure-value types (such asPoint,Color,Duration,Uuid,UserId(u64), or fieldless enums) where implicit copying is natural and cheap. - Avoid implementing
Copyon very large structs (such as a struct containing[u8; 4096]), where accidental implicit stack copies on every function call could hurt performance, or on types that might gain aString/Vecfield in a future version (since removingCopylater is a breaking API change).