C+
Ownership & safety · v0.0.13

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.

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:

{
    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.

Next

Continue with error handling.