thecodex.expert · The Codex Family of Knowledge
Rust

References and Slices

One mutable reference, or any number of immutable ones — never both at once. This single rule, enforced at compile time, is what eliminates data races in Rust.

Rust 1.96 Borrow checker Last verified:
Canonical Definition

A reference, written &T, lets code use a value without taking ownership of it — "borrowing" it temporarily. Rust’s borrowing rule, enforced by the compiler’s borrow checker: at any given time, a value can have either exactly one mutable reference (&mut T) or any number of immutable references (&T), but never both simultaneously. A slice (&[T], or &str for strings) is a reference to a contiguous portion of a collection, without owning or copying the underlying data.

Borrowing with & instead of taking ownership

Passing &value to a function lets it read the value without taking ownership — the caller keeps using the original afterward, unlike passing the value itself, which would move it.

Rustborrowing.rs
fn calculate_length(s: &String) -> usize {   // borrows, doesn't own
    s.len()
}

let s1 = String::from("hello");
let len = calculate_length(&s1);   // pass a reference
println!("{} is {} chars", s1, len);   // s1 still usable here!

The one rule: one mutable XOR many immutable

This single rule is what Rust checks at compile time to guarantee no data races: you cannot have a mutable reference alive at the same time as any other reference to the same data.

Rustborrow_rule.rs
let mut s = String::from("hello");

let r1 = &s;       // OK: immutable borrow
let r2 = &s;       // OK: another immutable borrow, allowed
println!("{} {}", r1, r2);

let r3 = &mut s;   // OK now that r1, r2 are no longer used
r3.push_str(" world");

// let bad = &s;    // if r3 were still in use here: COMPILE ERROR

Slices: a view into part of a collection

A slice references a contiguous range without copying it — &str (a string slice) is the most common example, and &[T] works the same way for any collection.

Rustslices.rs
let s = String::from("hello world");
let hello = &s[0..5];    // slice: "hello", no copy of the data
let world = &s[6..11];   // slice: "world"

let numbers = [1, 2, 3, 4, 5];
let middle = &numbers[1..4];   // &[2, 3, 4]

Sources

1
The Rust Project. The Rust Programming Language, "References and Borrowing" and "The Slice Type", doc.rust-lang.org/book/ch04.