← Back to Rust Course | Chapter 6: Borrowing & References | Lesson 3 of 6

Borrowing Rules

Rust has strict rules about sharing values so that nobody accidentally reads something while someone else is changing it.

The Core Borrowing Rule

Rust's borrowing rule is: at any given time, you can have either exactly one mutable reference, or any number of immutable references to a particular piece of data -- never both kinds simultaneously.

Example: The Core Borrowing Rule

markup
fn main() {
    let data = vec![1, 2, 3];
    let r1 = &data;
    let r2 = &data;
    println!("{:?} and {:?}", r1, r2);
}

Why the Rule Exists

This rule prevents data races at compile time: if code were reading a value while other code simultaneously changed it, the reader could see inconsistent or corrupted data. Rust simply disallows that possibility.

Example: Why the Rule Exists

markup
fn main() {
    let mut counter = 0;
    {
        let r = &mut counter;
        *r += 1;
    }
    println!("counter = {}", counter);
}

Non-Lexical Lifetimes

Modern Rust allows a reference's borrow to end as soon as it is last used, rather than only at the end of its enclosing block, making many previously-rejected patterns compile.

Example: Non-Lexical Lifetimes

markup
fn main() {
    let mut value = 5;
    let r1 = &value;
    println!("r1: {}", r1); // last use of r1
    let r2 = &mut value; // fine: r1's borrow has ended
    *r2 += 1;
    println!("value: {}", value);
}

References Must Always Be Valid

The borrow checker also guarantees a reference can never outlive the data it points to, eliminating dangling references entirely at compile time.

Example: References Must Always Be Valid

markup
fn main() {
    let owner = String::from("valid data");
    let borrowed = &owner;
    println!("{}", borrowed);
    println!("owner is still around: {}", owner);
}
Common Mistakes
  1. Trying to keep an immutable reference alive while also creating a mutable reference to the same data.
  2. Assuming borrow checker errors mean the code is fundamentally wrong, when often just reordering or shortening a scope fixes it.
  3. Forgetting that Non-Lexical Lifetimes let a reference's effective scope end at its last use, not at the end of the enclosing block.
Chapter Summary
  • At any time, you can have either one mutable reference, or any number of immutable references, but not both.
  • References must always be valid (point to data that has not been dropped) -- this is checked at compile time.
  • The borrow checker enforces these rules statically, adding no runtime cost.
  • Non-Lexical Lifetimes mean a reference's borrow ends at its last actual use, not necessarily at the end of its block.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.