Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Ownership and Borrowing

This chapter explains ownership and borrowing in a way that matches the mental model we developed:

  • ownership is not mainly about possession
  • ownership is about lifetime responsibility
  • borrowing is about access constraints

That distinction is the key:

  • ownership answers: who is responsible for how long the value lives
  • borrowing answers: how that value may be accessed right now

The Core Distinction

If I compress Rust's memory model into one line, it is this:

Ownership manages lifetime. Borrowing manages access.

That is the cleanest way to separate the two ideas.

What Ownership Is Doing

In Rust, a value usually has one controlling owner at a time.

Example:

#![allow(unused)]
fn main() {
let s = String::from("hello");
}

Here:

  • s is the binding that owns the String value
  • that binding is responsible for the value's lifetime
  • when the owner goes out of scope, the value is dropped

So the real job of ownership is:

  • one place is responsible for lifetime
  • one place is responsible for cleanup
  • ownership can move to another binding

That is why this is valid:

#![allow(unused)]
fn main() {
let s1 = String::from("hello");
let s2 = s1;
}

After the move:

  • s1 no longer owns the value
  • s2 now owns the value

This is why a good interview-safe translation is:

I think of ownership less as possession and more as lifetime responsibility.

What Borrowing Is Doing

Borrowing does not answer who owns the value. Borrowing answers who may access the value and in what way.

The most standard Rust rule is:

At any given time, Rust allows either many shared references or one exclusive mutable reference.

In code:

fn main() {
    let mut s = String::from("hello");

    let r1 = &s;
    let r2 = &s;
    println!("{r1} {r2}");

    let r3 = &mut s;
    r3.push_str(" world");
}

So borrowing is about:

  • shared read access through &T
  • exclusive write access through &mut T
  • avoiding conflicting access patterns

That is why the clean phrasing is:

Borrowing manages access through references.

Your Mental Model, Refined

Your original mental model was close:

  • there is one controlling owner of a value
  • many other bindings may read through references
  • only one mutable access is allowed at a time

The only missing piece was that the read/write rule is not the whole ownership model.

That rule is mostly the borrowing rule. Ownership adds the lifetime side:

  • who keeps the value alive
  • who is responsible for dropping it
  • who can transfer that responsibility

So the full version is:

Rust preserves memory safety by combining lifetime responsibility with access constraints.

Even more compact:

Ownership determines lifetime responsibility. Borrowing determines access constraints.

Access Constraints vs Lifetime Constraints

This is the distinction that matters most for interviews.

Lifetime constraints

These come from ownership.

They answer:

  • who owns the value
  • how long the value lives
  • when the value is dropped
  • whether the value has been moved

Example:

fn main() {
    let s = String::from("hello");
    let t = s;
    // s is no longer valid here
    println!("{t}");
}

This is a lifetime/ownership issue. The question is: which binding is responsible for the value now?

Access constraints

These come from borrowing.

They answer:

  • can the value be read through shared references
  • can the value be modified through an exclusive mutable reference
  • are there conflicting references alive at the same time

Example:

fn main() {
    let mut s = String::from("hello");

    let r1 = &s;
    // let r2 = &mut s; // not allowed here
    println!("{r1}");
}

This is an access/borrowing issue. The question is: what reference pattern is valid at this moment?

Bindings, Owners, Borrowers, References

These terms help keep the model precise.

  • owner: the binding currently responsible for the value's lifetime
  • borrower: the binding that holds a reference to the value
  • reference: the actual &T or &mut T
  • binding: the name bound to a value or reference

So instead of saying "entities," the Rust-safe phrasing is:

A value may be accessed through its owner or through borrowed references.

Or:

Borrowing determines what references may exist to a value at a given time.

User vs &User vs &mut User

These mean different lifetime and access relationships.

By value

#![allow(unused)]
fn main() {
struct User {
    name: String,
    active: bool,
}

fn by_value(user: User) {
    println!("{}", user.name);
}
}

This means:

  • the function takes ownership
  • the value moves into the function
  • the caller loses that owner binding

By shared reference

#![allow(unused)]
fn main() {
fn by_ref(user: &User) {
    println!("{}", user.name);
}
}

This means:

  • the function borrows the value
  • the caller keeps ownership
  • the function gets read access only

By mutable reference

#![allow(unused)]
fn main() {
fn by_mut_ref(user: &mut User) {
    user.active = false;
}
}

This means:

  • the function borrows the value mutably
  • the caller keeps ownership
  • the function gets exclusive mutable access

The Interview-Safe Explanation

If you want to explain the model without sounding tangled, use this:

Rust's memory safety comes from the combination of ownership and borrowing. Ownership gives every value a single place responsible for its lifetime and cleanup. Borrowing then controls access to that value: either many shared readers or one exclusive mutable access, but not both at the same time.

An even shorter version:

Ownership manages lifetime; borrowing manages access.

The Version Closest To Your Own Thinking

I don't think of ownership as possession so much as control over lifetime. The owner is the place that determines how long the value lives, and borrowing controls how that value can be accessed during that lifetime. That is the distinction that makes the whole model click for me.

Recall Checklist

  • Can I explain ownership without reducing it to "mine vs yours"?
  • Can I explain borrowing as an access rule over references?
  • Can I explain many readers vs one writer?
  • Can I explain why that still is not the whole model without lifetime responsibility?
  • Can I explain User, &User, and &mut User cleanly?
  • Can I explain the difference between move errors and borrow errors?