Rust references cheat sheet
A compact guide to where &, &mut, Box, and Option go in Rust type declarations.
The most basic forms
Plain value
let x: i32 = 5;
x owns an i32.
Shared reference
let x: i32 = 5;
let r: &i32 = &x;
r is a shared reference to x.
Mutable reference
let mut x: i32 = 5;
let r: &mut i32 = &mut x;
r is a mutable reference to x.
Option forms
Optional value
let x: Option<i32> = Some(5);
let y: Option<i32> = None;
The Option owns the i32 when it is Some.
Reference to an Option
let x: Option<i32> = Some(5);
let r: &Option<i32> = &x;
You definitely have a reference, and it points to an Option that may be Some or None.
Option containing a reference
let x: i32 = 5;
let r: Option<&i32> = Some(&x);
let n: Option<&i32> = None;
The optional part is the reference itself.
Mutable versions
let mut x: i32 = 5;
let r: Option<&mut i32> = Some(&mut x);
Box forms
Boxed value
let b: Box<i32> = Box::new(5);
b owns a heap-allocated i32.
Reference to a box
let b: Box<i32> = Box::new(5);
let r: &Box<i32> = &b;
This is a reference to the box itself.
Box containing an Option
let b: Box<Option<i32>> = Box::new(Some(5));
Option containing a Box
let x: Option<Box<i32>> = Some(Box::new(5));
These are different:
Box<Option<i32>>means the heap allocation always exists, and inside it is eitherSomeorNoneOption<Box<i32>>means the box itself may or may not exist
Common nested combinations
Reference to an Option of a value
let x: Option<i32> = Some(5);
let r: &Option<i32> = &x;
Option of a reference to a value
let x: i32 = 5;
let r: Option<&i32> = Some(&x);
Reference to an Option of a Box
let x: Option<Box<i32>> = Some(Box::new(5));
let r: &Option<Box<i32>> = &x;
Option of a reference to a Box
let x: Box<i32> = Box::new(5);
let r: Option<&Box<i32>> = Some(&x);
Option of a reference to the boxed value
let x: Box<i32> = Box::new(5);
let r: Option<&i32> = Some(&*x);
Reference to an Option of a reference
let x: i32 = 5;
let y: Option<&i32> = Some(&x);
let r: &Option<&i32> = &y;
Linked-list style declaration
This is very common in Rust:
type List<T> = Option<Box<Node<T>>>;
Read it inside out:
- a
List<T>is - an
Option - of a
Box - of a
Node<T>
So a list is either:
Nonefor the empty list, orSome(Box<Node<T>>)for a node on the heap
Example node type:
type List<T> = Option<Box<Node<T>>>;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Node<T> {
pub val: T,
pub next: List<T>,
}
A reference to the whole list:
let head: List<i32> = None;
let r: &List<i32> = &head;
A borrowed view into the node inside:
let head: List<i32> = Some(Box::new(Node { val: 1, next: None }));
let node_ref: Option<&Node<i32>> = head.as_deref();
Useful conversion helpers
as_ref()
Turns &Option<T> or Option<T> borrowing context into Option<&T>.
let x: Option<i32> = Some(5);
let r: &Option<i32> = &x;
let y: Option<&i32> = r.as_ref();
as_mut()
let mut x: Option<i32> = Some(5);
let y: Option<&mut i32> = x.as_mut();
as_deref()
Very handy for Option<Box<T>>.
let x: Option<Box<i32>> = Some(Box::new(5));
let y: Option<&i32> = x.as_deref();
It dereferences the Box for you while borrowing.
as_deref_mut()
let mut x: Option<Box<i32>> = Some(Box::new(5));
let y: Option<&mut i32> = x.as_deref_mut();
Pattern matching examples
Matching a borrowed Option
let x: Option<i32> = Some(5);
let r: &Option<i32> = &x;
match r {
Some(n) => println!("{n}"),
None => println!("none"),
}
Here n is &i32, because you matched through a shared reference.
Matching an Option<&T>
let x: i32 = 5;
let r: Option<&i32> = Some(&x);
match r {
Some(n) => println!("{n}"),
None => println!("none"),
}
Here too, n is &i32.
Matching mutable references
let mut x = Some(5);
if let Some(n) = x.as_mut() {
*n += 1;
}
Quick mental rules
Rule 1: & always applies to the thing immediately to its right
&Option<i32>
means “reference to Option<i32>”.
Option<&i32>
means “optional reference to i32”.
Rule 2: angle brackets show what a container holds
Option<T>holds a maybe-TBox<T>holds an owned heap-allocatedTVec<T>holds manyT
Rule 3: outer type matters most for ownership
Option<Box<T>>: the box may be absentBox<Option<T>>: the box is always present&Option<T>: borrowed optional valueOption<&T>: optional borrowed value
Mini table
| Type | Meaning |
|---|---|
T |
owned value |
&T |
shared reference to value |
&mut T |
mutable reference to value |
Option<T> |
maybe an owned value |
&Option<T> |
reference to an optional value |
Option<&T> |
maybe a reference |
Box<T> |
owned heap value |
Option<Box<T>> |
maybe a boxed value |
Box<Option<T>> |
boxed optional value |
&Box<T> |
reference to a box |