# The borrow checker

The rule is one line: **aliasing XOR mutability**. At any point in the program, a place has either any number of shared borrows, or exactly one exclusive borrow, never both.

```cplus
let mut v: vec::Vec[i32] = vec::new::[i32]();
v.push(1);
let n: usize = v.len();      // shared borrow — fine
let p: i32 = v.get(0);       // shared borrow — fine
v.push(2);                   // exclusive — but no live shared borrow now; fine
```

Because shared borrows can read but not mutate, and the single exclusive borrow is the only one allowed to mutate, two threads or two code paths can never hold a writer and a reader of the same place at once. That is why data races do not compile.

## The common diagnostics

- **E0372**: move out of a borrowed value.
- **E0383**: read while exclusively borrowed.
- **E0370** family: overlapping incompatible borrows.

## The fix is almost always a scope boundary

When two borrows conflict, the fix is usually to end one before the other begins, by introducing a scope so they do not co-exist:

```cplus
{
    let r: i32 = v.get(0);
    println(r);
}                            // shared borrow ends here
v.push(99);                  // exclusive borrow now fine
```

The borrow checker reasons within a function boundary. For the full picture of what it enforces versus what it trusts you to uphold (views and raw pointers), see [Ownership](/docs/ownership).

## Next

Continue with [error handling](/docs/error-handling).
