Ownership

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 Copy for small, pure-value types (such as Point, Color, Duration, Uuid, UserId(u64), or fieldless enums) where implicit copying is natural and cheap.
  • Avoid implementing Copy on 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 a String/Vec field in a future version (since removing Copy later is a breaking API change).