SyntaxStudy
Sign Up
Rust Immutable and Mutable References
Rust Beginner 1 min read

Immutable and Mutable References

Borrowing allows you to use a value without taking ownership of it. A borrow is represented by a reference: `&T` for an immutable reference and `&mut T` for a mutable one. The borrow checker enforces two rules at compile time: you can have any number of immutable references to a value at one time, or exactly one mutable reference — but never both simultaneously. These rules prevent data races entirely at compile time. Immutable references are created with the `&` operator and are the most common way to pass data to functions without moving it. Multiple immutable references to the same data can coexist because they promise not to modify the data — readers do not interfere with each other. The referenced value must live at least as long as the reference, a constraint the borrow checker enforces. Mutable references are created with `&mut` and grant exclusive write access. Because the borrow checker guarantees no other reference (mutable or immutable) can exist at the same time, mutation through `&mut T` is always safe — there are no aliased writes, no write-read races, and no tearing of data. The exclusivity of mutable references is one of the most important safety properties Rust provides.
Example
fn main() {
    // --- Immutable references ---
    let s = String::from("hello");
    let r1 = &s;
    let r2 = &s;    // multiple immutable refs are fine
    println!("r1={r1}  r2={r2}  s={s}");

    // --- Mutable reference ---
    let mut data = String::from("foo");
    append_bar(&mut data);
    println!("data = {data}");

    // --- Borrow checker prevents simultaneous mut + immut ---
    let mut v = vec![1, 2, 3];
    let first = &v[0];      // immutable borrow of v
    println!("first = {first}");
    // v.push(4);           // compile error: cannot borrow `v` as mutable
                            // because it is also borrowed as immutable
    // The immutable borrow ends after the last use of `first`
    v.push(4);              // now ok — first's lifetime has ended
    println!("v = {:?}", v);

    // --- Only one mutable reference at a time ---
    let mut x = 5;
    let m1 = &mut x;
    *m1 += 10;
    // let m2 = &mut x;     // compile error: second mutable borrow
    println!("x = {x}");
}

fn append_bar(s: &mut String) {
    s.push_str("bar");
}