liveBook · Manning

FnOnce

As explained in Learn Rust in a Month of Lunches

FnOnce is a Rust callable trait for closures and function-like values that may consume their captured environment and therefore can be called at most once.

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:

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

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains capture behavior, single-call examples, generic bounds, and the supertrait relationship; does not develop trait implementation internals.
Examples
Uses a consumed vector, a dropped String, and a compiler warning about borrowing a String in a thread.
What it assumes
Assumes basic closure capture and ownership, while walking through how a generic function signature specifies a closure trait.
What you can do after
Build it from scratch: write a generic function with an FnOnce() bound and call its closure once.
How it connects
Connects closure capture and ownership to Fn, FnMut, supertraits, and thread spawning.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.