← The log

· 1 min read

Understanding Rust's Ownership Model

A practical walkthrough of how Rust's ownership and borrowing work — and why they matter for writing safe, concurrent systems.

MemoryFundamentals

Rust's ownership model is the language's defining feature. It lets you write safe, performant systems code without a garbage collector — and without the class of bugs that haunt C and C++ programs.

Ownership in 30 seconds

Every value in Rust has exactly one owner. When the owner goes out of scope, the value is dropped. That's it.

fn main() {
    let s = String::from("hello"); // s owns the String
    let t = s;                     // ownership moves to t
    // println!("{}", s);          // compile error: s is moved
    println!("{}", t);             // works fine
}

The compiler enforces this at compile time. No runtime checks, no garbage collection pauses.

Why it matters

Memory bugs — use-after-free, double-free, dangling pointers — are impossible in safe Rust. Not "unlikely." Impossible. The compiler rejects programs that would cause them.

This is the billion-dollar mistake made safe.

Borrowing

Ownership would be useless if you couldn't share data. Borrowing lets you lend access without transferring ownership:

fn length(s: &String) -> usize {
    s.len() // we borrow s, not own it
}

fn main() {
    let s = String::from("hello");
    let len = length(&s);
    println!("{} has {} characters", s, len); // s still valid
}

The rules are simple:

  • You can have many immutable borrows (&T) at once, or
  • Exactly one mutable borrow (&mut T) — but not both.

This prevents data races at compile time.

What comes next

In practice, ownership becomes second nature within a few weeks. The compiler error messages are some of the best in any language — they tell you exactly what's wrong and often suggest a fix.

If you want to go deeper, read through the Rust Book chapters on ownership. It's free, well-written, and worth every minute.

Keep reading