Concept · Rust

The borrow checker

Many shared references or one mutable reference, never both — the compile-time rule that rules out dangling pointers and data races.

3 minborrowingreferencesaliasing xor mutation&mut

A borrow is a reference to a value that someone else owns. The borrow checker is the part of the Rust compiler that checks every borrow against one rule:

At any moment, a value can have either any number of shared references (&T) or exactly one mutable reference (&mut T) — and no reference may outlive the value.

Shortened: aliasing XOR mutation. Many readers or one writer.

What it prevents

rust
let mut v = vec![1, 2, 3];
let first = &v[0];   // shared borrow
v.push(4);           // error[E0502]: needs a mutable borrow while `first` is alive
println!("{first}");

push may reallocate the vector's buffer, which would leave first pointing at freed memory — iterator invalidation, a classic C++ crash. The same rule makes data races impossible: a race needs two accesses with at least one write and no ordering, and "one writer, no readers" forbids exactly that.

Borrows end at their last use

Borrows are non-lexical: a reference's borrow lasts until it's last used, not until the end of the block. Many borrow errors are fixed just by reordering — finish reading before you start writing — or by copying a small value out instead of holding a reference to it.

Reading its errors

Every borrow error points at three places: where the first borrow starts, where the conflicting borrow happens, and where the first borrow is used later. Shrink one of them so they don't overlap. When the rule really doesn't fit the problem — shared mutable state — move the check to runtime with interior mutability.

How long a reference may live across function boundaries is described with lifetimes.

Learn it in depth