🎓 A1Learner
🔍

Rust Reference Patterns

A reference pattern matches against a reference instead of moving a value. The & shape matches a reference itself.

An & inside the pattern

Matching a reference against &x takes one & off each side. x binds the value behind the reference:

let point = &5;
match point {
    &x => println!("x = {x}"),
}

ref borrows instead of taking

A plain name would move the text out of the Option. ref binds by borrowing instead, so the Option keeps its text and stays usable:

let gift = Some(String::from("book"));
if let Some(ref title) = gift {
    println!("the gift is a {title}");
}
println!("gift kept: {:?}", gift);

ref mut borrows so you can change

Borrow mutably and you can change the value through the reference. The star follows the reference to the value behind it:

let mut score = Some(10);
if let Some(ref mut n) = score {
    *n += 5;
}
println!("score = {:?}", score);

Loops hand you references too

iter() lends each item, so name is a &str each round. A literal pattern is written with & in front of it:

let names = ["Rex", "Ferris"];
for name in names.iter() {
    match name {
        &"Ferris" => println!("found Ferris"),
        _ => println!("someone else"),
    }
}

Example

fn main() {
    let name = Some(String::from("Ferris"));
    match name {
        Some(ref s) => println!("borrowed {}", s),
        None => println!("none"),
    }
    println!("still usable: {:?}", name);
    let mut count = Some(5);
    if let Some(ref mut n) = count {
        *n += 1;
    }
    println!("count = {:?}", count);
}

Key points

  • Destructuring is not dereferencing: * follows a reference in an expression, while &, ref, and ref mut are shapes inside a pattern
  • Both shapes let code look at a value without taking it.

In this example, Some(ref s) borrows the text instead of moving it. The arm prints borrowed Ferris through the reference s. Because nothing moved, name is still whole afterwards, and the second line prints it in full. Below, count holds Some(5). The pattern Some(ref mut n) borrows the number mutably. So *n += 1 raises it to 6. The last line shows count = Some(6). Two words, ref and ref mut, chose borrowing over taking.

Note

Modern Rust often adds the borrowing for you when a pattern meets a reference (called match ergonomics).

ref and & still earn their place: they say exactly what you meant, and older code is full of them.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

In the pattern Some(ref s), what is s?