Rust's Copy Trait: Implicit Bitwise Duplication
Rust's `Copy` trait makes assignments duplicate a value instead of moving it, allowing the original to still be used. It's an implicit, bitwise copy for simple types like integers.
WHY IT EXISTS By default, Rust uses move semantics to enforce its ownership rules, ensuring memory safety. However, for simple data types like integers, moving the value and invalidating the original variable is often inconvenient. The Copy trait exists to opt-in to cheaper, more ergonomic 'copy semantics' for types where a simple bit-for-bit duplication is safe and logical.
THE MENTAL MODEL A type that is Copy is cheap to duplicate. Think of it like photocopying a document. When you assign a Copy type with let y = x;, you get a brand new, independent copy (y), and the original (x) is still perfectly usable. This is the opposite of a 'move', which is like handing the single original document to someone else, leaving you with nothing.
HOW IT WORKS A type can implement Copy only if all of its fields also implement Copy. You typically add it via #[derive(Copy, Clone)]. The Clone trait is a required supertrait. For a Copy type, the compiler performs an implicit, bitwise copy during assignments, function calls, and other operations. This behavior is not overloadable. This contrasts with Clone, which is always an explicit action (x.clone()) and can contain complex logic to duplicate a value, such as allocating new memory on the heap.
WHEN TO USE IT Generally, if your type can be Copy, it should be. This applies to types that are just collections of bits without any ownership of external resources. Good candidates include primitive types (i32, f64, bool), shared references (&T), and structs or tuples composed entirely of other Copy types. Implementing Copy makes using the type more ergonomic.
WHEN NOT TO USE IT A type cannot be Copy if it implements the Drop trait, which signifies it manages a resource like heap memory or a file handle. A simple bitwise copy would create two pointers to the same resource, leading to a double-free error. This is why String and Vec are not Copy. Also, avoid implementing Copy on a public type if you suspect it might need to manage a resource in the future, as removing the trait is a breaking API change.
ONE CANONICAL EXAMPLE A struct Point { x: i32, y: i32 } can be Copy because its field, i32, is Copy. An assignment let p2 = p1; creates a new Point, and both p1 and p2 are usable. In contrast, a struct PointList { points: Vec<Point> } cannot be Copy because its field points is a Vec, which is not Copy. Attempting to derive Copy on PointList will result in a compiler error.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.