Fn, FnMut & FnOnce
Closures implement Fn (shared borrow), FnMut (mut borrow), or FnOnce (consume captures) based on usage.
Recipe
fn call_twice(f: impl Fn() -> i32) -> i32 {
f() + f()
}
fn main() {
let n = 10;
println!("{}", call_twice(|| n));
}When to reach for this: Bounding closure parameters in generic APIs (thread::spawn needs FnOnce).
Working Example
fn with_mut(f: impl FnMut(&mut Vec<i32>)) {
let mut v = vec![1];
f(&mut v);
}
fn main() {
with_mut(|v| v.push(2));
}What this demonstrates:
FnMutfor mutating captured state or mut ref argsFnOncerequired if closure consumes capturedString- Compiler picks minimal trait impl
Deep Dive
Fn is subtrait of FnMut is subtrait of FnOnce. Prefer impl Fn when possible for flexibility.
Gotchas
- Spawn requires
FnOnce + Send + 'static- Captures must be owned. Fix:moveclosure. - Storing
FnMuttrait object -Box<dyn FnMut()>. Fix: Box or generic. - Calling FnOnce twice - Compile error. Fix: Call once or clone data before.
- Conflicting captures - Move and borrow same variable. Fix: Restructure captures.
- Method refs in closure - Auto trait impl may be
FnMut.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
Function pointer fn() | No capture | Need environment |
Generic F: FnOnce | Flexible callback | Need homogenous vec of callbacks |
Box<dyn FnMut()> | Runtime storage | Monomorphization ok |
FAQs
Which trait chosen?
Compiler analyzes captures and calls.dyn Fn?
Object safe for shared call.async closure?
Rust 1.85+ async closures evolving - check edition.Fn trait hierarchy?
Fn implies FnMut implies FnOnce.thread spawn?
FnOnce + Send + 'static.sort_by closure?
FnMut comparing elements.Iterator map?
FnMut per element.copy captures?
Move or Copy types captured by value.refcell closure?
FnMut borrowing RefCell.test?
Assert call count with Cell.Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.