Ownership

Copy Types

A Copy type is a type whose values can be duplicated cleanly and completely by a simple bitwise copy of stack memory (memcpy), without needing to allocate heap memory or duplicate external system resources. When a type implements the Copy marker trait, assigning it to another variable or passing it by value to a function copies the value instead of moving it, leaving the original variable valid and initialized.

Move vs Copy Behavior

For a Copy type such as i32, let y = x; copies the 4 bytes on the stack and leaves both x and y usable:

Stack Layout for `let x: i32 = 42; let y = x;`:
  +---------------+
  | x: i32 = 42   |  <-- Remains valid and initialized!
  +---------------+
  | y: i32 = 42   |  <-- Independent 4-byte bitwise copy
  +---------------+
fn print_number(n: i32) {
    println!("Inside function: n = {n}");
}

fn main() {
    let x: i32 = 42;
    let y = x; // Bitwise copy (`i32` implements `Copy`)

    print_number(x); // Passes another copy of `x`

    // Both `x` and `y` remain completely valid:
    println!("After assignment and call: x = {x}, y = {y}");
}
Inside function: n = 42
After assignment and call: x = 42, y = 42

Built-In Types That Implement Copy

Category Types That Are Copy Why They Are Safe to Copy Bit-for-Bit
Integers i8..i128, isize, u8..u128, usize Pure stack bit patterns with no heap pointers or destructors
Floats f32, f64 Pure 4-byte or 8-byte IEEE 754 bit patterns
Booleans & Characters bool, char, () Self-contained 1-byte, 4-byte, or 0-byte stack values
Shared References &T (for any T, even &String or &Vec<T>!) Copying a read-only pointer just creates another shared reader
Raw Pointers & fn Pointers *const T, *mut T, fn(A) -> B Plain machine addresses with no automatic destructor
Arrays [T; N] [T; N] if and only if T: Copy Contiguous block of N copyable elements on the stack
Tuples (T1, T2, ...) (T1, T2, ...) if and only if all elements are Copy Contiguous stack fields that are all copyable
Option<T> / Result<T, E> Option<T> / Result<T, E> when T: Copy (and E: Copy) Tag + copyable payload on the stack
fn main() {
    let pair: (i32, bool) = (10, true);
    let fixed_arr: [u8; 3] = [1, 2, 3];
    let text = String::from("shared");
    let shared_ref: &String = &text;

    // All three assignments below perform implicit bitwise copies:
    let pair_copy = pair;
    let arr_copy = fixed_arr;
    let ref_copy = shared_ref;

    println!("Originals still valid: {pair:?}, {fixed_arr:?}, '{shared_ref}'");
    println!("Copies:                {pair_copy:?}, {arr_copy:?}, '{ref_copy}'");
}
Originals still valid: (10, true), [1, 2, 3], 'shared'
Copies:                (10, true), [1, 2, 3], 'shared'

Types That Are NOT Copy

Type Why It Cannot Be Copy
String, Vec<T>, Box<T> Owns a heap buffer; bitwise copying the stack header would cause a double free when both copies drop
std::fs::File, TcpStream Owns an OS descriptor that must be closed once
&mut T (Mutable reference) Must remain exclusive; copying &mut T would create two simultaneous mutable aliases to the same data
[String; 2] or (i32, String) Contains at least one non-Copy field (String)