What is Ownership? #

  • Ownership is Rust’s unique memory management system that ensures memory safety without a garbage collector.
  • It’s a set of rules enforced at compile time that determines how memory is allocated, accessed, and freed.
  • Ownership prevents common memory bugs like dangling pointers, double frees, and memory leaks while maintaining zero-cost abstractions.

Ownership Rules #

Rust’s ownership system follows three fundamental rules:

1. Each value in Rust has an owner

let s = String::from("hello"); // 's' owns the String value

2. There can only be one owner at a time

let s1 = String::from("world");
let s2 = s1; // s1 is no longer valid, s2 is now the owner

3. When the owner goes out of scope, the value will be dropped
When a variable goes out of scope, Rust automatically calls a special function called drop() to clean up the memory, eliminating the need for manual memory management or garbage collection.

{
    let s = String::from("temp");
} // 's' goes out of scope here, memory is automatically freed

Stack vs Heap Allocation #

AspectStack AllocationHeap Allocation
SizeFixed size, known at compile timeDynamic size, unknown at compile time
Access SpeedFast (LIFO – Last In, First Out)Slower (requires pointer dereferencing)
Memory ManagementAutomatic cleanup when scope endsManual management (handled via ownership)
Typical UsagePrimitive and simple types (eg. int)Complex and dynamically sized types (eg. string)
Stack (Fast, Fixed Size)          Heap (Flexible, Dynamic Size)
┌─────────────────────┐          ┌─────────────────────────────┐
│ i32: 42             │          │ String data: "hello world"  │
│ bool: true          │          │ Vec data: [1, 2, 3, 4, 5]   │
│ char: 'A'           │          │ HashMap data: {...}         │
│ pointer to heap ────┼──────────┤                             │
└─────────────────────┘          └─────────────────────────────┘

Shallow Copy vs Deep Copy #

AspectShallow CopyDeep Copy
What gets copiedOnly metadata (pointer, length, capacity)Metadata and actual data
Data OwnershipShared underlying heap dataIndependent heap copies
PerformanceFastSlower
SafetyCan lead to double-free or data corruptionSafer, no shared ownership issues

Move, Clone, and Copy Scenarios #

1. Move #

Applies to heap / dynamic data types.

let s1 = String::from("hello");
let s2 = s1; // s1 is MOVED to s2
// println!("{}", s1); // Compile error! s1 is no longer valid
println!("{}", s2); // Works fine

2. Assigning New Value to Existing Variable #

let mut s = String::from("hello");
s = String::from("world"); // Old "hello" is dropped immediately
println!("{}", s); // Prints "world"

3. Clone #

It is an explicit Deep Copy

let s1 = String::from("hello");
let s2 = s1.clone(); // Explicit deep copy
println!("s1: {}, s2: {}", s1, s2); // Both valid

4. Copy #

Applies to Stack only types that support “Copy” trait.
Example: Integer i32 type implements “Copy” trait and it has a fixed size hence it is trival to copy as it sits on stack

let x = 5;
let y = x; // Copy semantics (both remain valid)
println!("x: {}, y: {}", x, y); // Both valid

Types that implement Copy:

  • All integer types (i32, u64, etc.)
  • Boolean (bool)
  • Floating point (f32, f64)
  • Character (char)
  • Tuples (if all elements implement Copy)

Understanding Traits: Copy vs Drop #

Traits in Rust define shared behavior that types can implement. Think of them as contracts that specify what a type can do.

// Trait example (simplified)
trait Copy {
    // Types implementing Copy can be duplicated by copying bits
}

trait Drop {
    fn drop(&mut self) {
        // Custom cleanup code when value goes out of scope
    }
}

Copy and Drop are mutually exclusive:

  • Copy trait: Types that can be safely duplicated by simply copying their bits (stack-only data)
  • Drop trait: Types that need custom cleanup when going out of scope (usually heap-allocated data)

Why they can’t coexist: If a type implements Copy, Rust assumes it’s safe to duplicate by copying bits. But if it also needs Drop (custom cleanup), copying would create multiple owners of the same resources, leading to the double-free problem ownership is designed to prevent.