Course contentsShow
← Rust
Lesson 339 of 1,9104. Lifetimes and Advanced OwnershipFree lesson

The Copy Trait Semantics

Distinguish between bitwise copy and move semantics for stack-allocated types.

In this lesson, you will learn why some types are automatically duplicated when assigned to a new variable while others are transferred, a distinction known as the Copy trait semantics.

The Default: Move Semantics

By default, Rust follows move semantics. When you assign a variable to another, the ownership of the underlying data is transferred. If you have a type like String, which owns heap-allocated memory, Rust simply copies the pointer, length, and capacity to the new variable and invalidates the old one. This prevents "double-free" errors, where two variables try to drop the same memory.

The Exception: Bitwise Copy

Some types do not own heap resources; they live entirely on the stack. For these types, Rust allows a "bitwise copy." If a type implements the Copy trait, assigning one variable to another performs a simple, fast memory copy of the bits. The original variable remains valid and usable.

Consider these two examples:

// A move-only type (String)
let s1 = String::from("hello");
let s2 = s1; 
// println!("{}", s1); // Error: s1 was moved!

// A Copy type (i32)
let x1 = 42;
let x2 = x1;
println!("x1 is still valid: {}, x2 is: {}", x1, x2);

Why the Difference?

The compiler treats these differently because of what they represent. An i32 is just a collection of bits that has no "external" obligations—copying it doesn't leave a heap allocation dangling. Because it is cheap and safe to duplicate, Rust allows it to happen implicitly.

However, you cannot implement Copy for types that own resources (like String or Vec) because copying them would lead to multiple variables trying to manage the same heap memory, violating Rust's core promise of memory safety. By restricting Copy to simple, stack-only data, Rust ensures that if a type is expensive to clone or manages complex resources, you are forced to be explicit about it (usually by calling .clone()).

Key Takeaway: Types that only contain stack-allocated data can implement Copy to allow implicit bitwise duplication, while types managing heap resources must follow move semantics to ensure singular ownership.