🎓 A1Learner
🔍

Rust References

A reference is a borrow that lets code read or change a value without owning it. A shared reference, &, allows many readers at once.

Change a value through &mut

Borrow mutably, then write through the reference with *:

let mut count = 10;
let r = &mut count;
*r += 5;
println!("{}", r);

Many readers at once

Shared borrows may pile up freely — reading never clashes with reading:

let s = String::from("rust");
let a = &s;
let b = &s;
println!("{} {}", a, b);

A reference can point elsewhere

let mut r makes the reference itself changeable. Writing r = &b points it at a new value. a and b never change — only where r looks. (The opposite shape, let r: &mut T, is one fixed reference that may change the value it points at.)

let a = 10;
let b = 20;
let mut r = &a;
println!("{}", r);
r = &b;
println!("{}", r);

Passing a &mut does not spend it

Each call reborrows r. The function gets a fresh, short borrow through it. And r itself survives. That is why the same r can be passed twice:

fn add_one(n: &mut i32) {
    *n += 1;
}
let mut x = 1;
let r = &mut x;
add_one(r);
add_one(r);
println!("{}", r);

End a borrow at an exact line

Wrap a borrow in its own { } block. It ends at the closing brace. This is a clean way to take two mutable borrows one after the other:

let mut s = String::from("hi");
{
    let r = &mut s;
    r.push_str("!");
}
s.push_str("?");
println!("{s}");

Example

fn main() {
    let mut s = String::from("hello");
    let r = &mut s;
    r.push_str(", world");
    println!("{}", r);
    println!("{}", s); // borrow ended at last use of r
}

Key points

  • At any moment: many & borrows OR exactly one &mut borrow — never both
  • You cannot return a reference to a local variable — it would point at freed memory
  • One value can still be borrowed in separate pieces: two different fields may be borrowed mutably at once

In this example, s is a mutable String. r borrows it with &mut s. Through r, push_str adds ", world" to the text. The first println! prints r: hello, world. After that line, r is never used again, so its borrow ends. That is why the second println! can use s directly, and it shows the same changed text. Try adding another use of r after that line, and the compiler will complain — the borrow would still be alive.

Note

This "many readers or one writer" rule is why Rust can promise no data races.

Two threads can never change the same data at the same time through references.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

Which combination of borrows is allowed at the same time?