FnOnce is a Rust trait for a callable value that can be called at least once. A closure needs it when calling the closure consumes something it captured. After that call, the consumed value is gone, so that closure cannot be called again. section 11.6.3
A closure’s use of captured values helps explain the three callable traits:
- Fn reads through a shared reference and can be called repeatedly. section 11.6.3
- FnMut can change a captured value and can also be called repeatedly. section 11.6.3 section 12.1.1
- FnOnce can consume a captured value. Every closure implements FnOnce, including closures that also implement Fn or FnMut. section 11.6.3 section 12.1.2
Accepting a closure that consumes a value
A function can write `F: FnOnce()` to accept a closure taking no arguments and returning nothing, then call `f()` once. In the example, the closure calls `into_iter()` on a vector, consuming it. Trying to use that vector in a second closure produces a moved-value compiler error; borrowing with `iter()` instead permits the two calls shown in the alternative example. section 12.1
fn do_something<F>(f: F)
where
F: FnOnce(),
{
f();
}
fn main() {
let some_vec = vec![9, 8, 10];
do_something(|| {
some_vec
.into_iter()
.for_each(|x| println!("The number is: {x}"));
});
}
See a complete generic function that accepts an FnOnce closure and calls it once while the closure consumes a vector. section 12.1
FnOnce also appears in thread-spawning signatures. If a thread closure borrows a local String, the compiler warns that the closure may outlive the borrowed value. Adding `move` makes the closure own its capture and resolves that borrowing problem. The practical question is whether a closure only reads a capture, changes it, or consumes it—and whether the caller needs to invoke it again. section 11.6.4 section 11.6.3
