RUST.QUEST

An expedition through ownership, borrowing, and beyond.

Begin the Quest
I
CHAPTER ONE

OWNERSHIP

In Rust, every value has a single owner. When the owner goes out of scope, the value is dropped. This is the first rule of the terrain -- every resource belongs to someone, and when that someone departs, the resource returns to the earth.

Ownership is not a constraint. It is a contract between the programmer and the machine: in exchange for tracking who holds what, the compiler guarantees there are no dangling references, no use-after-free, no double-free. The path is narrow but safe.

let s1 = String::from("hello");
let s2 = s1; // s1 is moved to s2
// s1 is no longer valid here
II
CHAPTER TWO

BORROWING

When you need to use a value without claiming ownership, you borrow it. A reference lets you read -- or, with permission, write -- without taking possession. The borrow checker ensures that no reference outlives the data it points to.

Immutable borrows allow many readers. Mutable borrows allow exactly one writer. Never both at once. This discipline prevents data races at compile time, not runtime.

fn calculate(s: &String) -> usize {
s.len() // borrow, don't own
}
let s = String::from("world");
let len = calculate(&s); // s is still valid
III
CHAPTER THREE

LIFETIMES

Lifetimes are the compiler's way of tracking how long references are valid. Every reference in Rust has a lifetime -- usually inferred, sometimes annotated. They ensure that borrowed data always outlives the borrower.

The lifetime annotation syntax uses an apostrophe: 'a, 'b, 'static. These are not runtime constructs; they exist only at compile time, guiding the borrow checker through complex reference relationships.

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}