Skip to content

Chapter 1 of 8

Ownership Rules and Memory

Rust's ownership system rests on three simple rules that govern every value in the language: every value has exactly one owner, there can only be a single owner at any given moment, and the value is dropped when that owner goes out of scope. The "drop" here is not a casual phrase — it means the standard library's drop function from the Drop trait is called automatically at the closing brace of the variable's scope, freeing any resources the value owns. This pattern, sometimes called RAII (Resource Acquisition Is Initialization), ties resource lifetimes to object lifetimes so that cleanup is guaranteed by the structure of the program rather than by the discipline of the programmer.

The distinction between the stack and the heap is essential to understanding why these rules matter. The stack is a last-in, first-out region of memory for values whose size is known at compile time — integers, booleans, characters, and tuples of such primitives live there directly. The heap is used for values whose size or lifetime is dynamic, and accessing them is done through pointers stored on the stack. A String, for example, has a small struct (a pointer, length, and capacity) sitting on the stack, while the actual UTF-8 bytes it owns are stored on the heap. When the String goes out of scope, the heap buffer is freed at the same time as the stack-resident struct, preventing the leaks and double-frees that plague languages with manual memory management.

Scope in Rust is delimited by curly braces, and variables are dropped at the closing brace that introduced them. Even constructs like match arms create fresh scopes, so bindings introduced inside an arm are dropped when that arm completes. Shadowing, declared with a second let using the same name, does not move or drop the previous binding — it simply rebinds the name to a new value, and crucially, the new binding may have a different type. This is distinct from mutation with let mut, which keeps the same binding and type in place but changes the underlying value. Shadowing can therefore change a variable's type across declarations, while mutation cannot.

All chapters
  1. 1Ownership Rules and Memory
  2. 2Moves, Copy, and Clone
  3. 3Borrowing and the Borrow Checker
  4. 4Lifetimes, Variance, and PhantomData
  5. 5Slices, Strings, and Deref Coercion
  6. 6Interior Mutability and Runtime Enforcement
  7. 7Shared Ownership Across Threads
  8. 8Patterns, Iteration, and Unsized Types

Drill it

Reading is not remembering. These come from the Rust Ownership And Borrowing Explained deck:

Q

What are the three ownership rules in Rust?

Each value in Rust has an owner. There can only be one owner at a time. When the owner goes out of scope, the value is dropped.

Q

What happens to a value when its owner goes out of scope in Rust?

It is dropped — its drop function runs and its memory is freed.

Q

Which standard library function is called when a value goes out of scope?

drop, from the Drop trait, is called automatically at the end of the variable's scope.

Q

What is a "move" in Rust?

A transfer of ownership: assigning a value to another variable or passing it to a function moves the value, invalidating the source binding.