# The borrow checker

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

Concept · Rust · https://levelcode.org/concepts/borrow-checker

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](https://levelcode.org/concepts/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](https://levelcode.org/concepts/interior-mutability).

How long a reference may live across function boundaries is described with [lifetimes](https://levelcode.org/concepts/rust-lifetimes).
