Ownership

  • One owner per value.
  • When the owner goes out of scope, the value is freed.
  • Moving a value hands the keys to a new owner.

Borrowing lets multiple parts of your program read (or temporarily edit) a value without transferring ownership.

fn main() {
    let s = String::from("rust");       // s owns the heap data
    let len = calculate_length(&s);     // borrow immutably
    println!("'{s}' is {len} bytes long");
}

fn calculate_length(text: &String) -> usize {
    text.len()                          // read-only access
}

Immutable References (&T)

Analogy: Passing a photocopy of a library book. Everyone can read, nobody can scribble.

  • we can create any number of &T references simultaneously.
  • The original owner maintains full control and is still usable.
    let a = String::from("rust");

    let ref1 = &a;
    let ref2 = &a;
    println!("{ref1} - {ref2}");        // both fine

Mutable References (&mut T)

with mut we can modify the borrowed variable.

    let mut s = String::from("mutable");

    change(&mut s);
    println!("{s}");                    // prints "mutable string"

    fn change(task: &mut String) {
        task.push_str(" string");
    }

If we have a mutable reference to a value, we can have no other references to that value.

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

    let r1 = &mut s;
    let r2 = &mut s;

    println!("{}, {}", r1, r2);         // This fails

The Rules of References

  • At any given time, you can have either one mutable reference or any number of immutable references.
  • References must always be valid.