SkillByAIOpen interactive version →

Lesson 9 / 25

The Aliasing Rule

Many readers or one writer.

Shared XOR mutable

At any time you can have either any number of shared references or exactly one mutable reference to a value, not both. This rule prevents data races and iterator invalidation: pushing to a Vec may reallocate its buffer, which would leave an existing reference to an element dangling. The borrow checker tracks how long each borrow is used (non-lexical lifetimes), so a borrow ends after its last use, not at the end of the block.

Pushing while an element is borrowed, compile error

I compiled this with Rust 1.99.0 (cargo build); it is meant to fail. The output is trimmed to the error lines. Holding a reference to the first score and then pushing (which could reallocate the vector) is rejected with E0502: cannot borrow as mutable because it is also borrowed as immutable.

fn main() {
    let mut scores = vec![90, 75, 60];
    let first = &scores[0];   // shared borrow
    scores.push(100);         // mutable borrow while `first` is still used
    println!("first = {first}");
}

Output:

error[E0502]: cannot borrow `scores` as mutable because it is also borrowed as immutable
 --> src/main.rs:4:5
error: could not compile `demo` (bin "demo") due to 1 previous error

Copy out small values

let first = scores[0]; (copying the i32) instead of a reference ends the borrow immediately.

Quick check: Which combination of references does Rust allow at the same time?

  • One shared and one mutable
  • Many mutable references
  • Many shared references, or one mutable reference
  • Unlimited references of any kind
Answer

Many shared references, or one mutable reference — Prevents data races at compile time.