Beginner Fundamentals

Borrowing

Borrowing lets you access a value without taking ownership of it. You create a reference with &, which the function can read but does not own.

Immutable references

fn length(s: &String) -> usize {
    s.len()
} // s is a reference, nothing is dropped here

fn main() {
    let text = String::from("borrowing");
    let len = length(&text); // lend a reference
    println!("{} has {} chars", text, len); // text still usable
}

Mutable references

To modify borrowed data, use &mut. The original variable must be mutable too.

fn add_excitement(s: &mut String) {
    s.push('!');
}

fn main() {
    let mut text = String::from("hello");
    add_excitement(&mut text);
    println!("{}", text); // hello!
}

The borrowing rules

At any given time you may have either:

  • Any number of immutable references (&T), or
  • Exactly one mutable reference (&mut T).

You cannot mix them at the same time.

fn main() {
    let mut value = 10;
    let r1 = &value;
    let r2 = &value; // many immutable refs are fine
    println!("{} {}", r1, r2);

    let m = &mut value; // ok now that r1 and r2 are no longer used
    *m += 1;
    println!("{}", m);
}

These rules prevent data races at compile time.