Closures Best Practices
How to Use This List
- Review callback-heavy code (iterators, threads, async).
- Prefer minimal capture and clear
moveintent.
A - Capture Discipline
- Capture minimally - prefer references for short closures. Less move churn.
- Use
moveonly when ownership or thread spawn requires it. Document why. - Clone before
moveif both parent and child need data.Arcfor shared. - Avoid capturing large structs by move. Capture
Arcor indices. - Prefer
impl Fnin generic APIs overBox<dyn Fn>when possible. Zero-cost.
B - Traits and Bounds
- Use loosest closure trait that works (
Fn>FnMut>FnOnce). Flexible callers. - Thread bounds:
FnOnce + Send + 'static. No stack borrows. - Do not hold
RefCellacross thread boundary. UseMutex. - Return
impl Fnfor unique closure types.Box<dyn Fn>for heterogeneity. - Name non-trivial closures via variables. Readability in long chains.
C - Iterators
- Keep adapter chains readable (<= 5 steps) or extract functions. Maintenance.
- Avoid clone in
mapwithout need. Borrow withfilteron references. - Use
filter_mapandfoldidioms. Fewer passes. - Heed
needless_collectclippy lint. Performance smell. - Use
rayononly for CPU-bound parallel. Not I/O.
D - Debugging
- If closure fails to compile, check move vs borrow spans. Classic errors.
- Explicit types on closure params when inference confuses. API boundaries.
- Test HOFs with simple closure doubles. Behavior verification.
- Document closure thread-safety in public APIs. Send/Sync expectations.
- Avoid recursive untyped closures. Use named fn.
FAQs
move always for threads?
Yes for detached threads.async move?
Common in tokio spawn.clone in loop closure?
Move cloned value per iteration if needed.Fn in struct?
Boxdebug closure type?
Compiler error shows unique type name.lint redundant move?
clippy may suggest.capturing self?
Method-like closures need careful borrow/move.wasm?
Closures work; threading limited.no_std?
Closures supported.next?
Smart pointers for shared captures.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+.