> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust FnOnce Closure

`FnOnce` is a trait implemented by all closures in Rust, specifically representing closures that can be called at least once. When a closure strictly implements `FnOnce` (and not its subtraits `FnMut` or `Fn`), it means the closure consumes the variables it captures from its enclosing environment, taking ownership of them. Because the environment is consumed during execution, the closure cannot be invoked a second time.

## Trait Signature

The mechanics of `FnOnce` are defined by its trait signature in the standard library:

```rust theme={"dark"}
pub trait FnOnce<Args> {
    type Output;
    fn call_once(self, args: Args) -> Self::Output;
}
```

The defining characteristic here is the `self` receiver in `call_once`. Unlike `FnMut` (which takes `&mut self`) or `Fn` (which takes `&self`), `FnOnce` takes `self` by value. This moves the closure instance—and its captured environment—into the method, consuming it entirely.

## Execution Mechanics

A closure is inferred by the compiler to be strictly `FnOnce` if the body of the closure moves a captured variable out of the closure's internal state. This typically happens when the closure drops the value, returns it, or passes it to another function that requires ownership.

```rust theme={"dark"}
let data = String::from("environment data");

// The compiler infers this closure as strictly `FnOnce`
let consume_closure = || {
    // `data` is moved out of the closure's environment into `_consumed`
    let _consumed = data; 
};

consume_closure(); // `call_once(self)` is executed, consuming the closure.

// consume_closure(); // COMPILER ERROR: closure cannot be invoked more than once
```

## Trait Hierarchy

In Rust's closure trait hierarchy, `FnOnce` is the foundational supertrait:

* `FnMut` requires `FnOnce` (`trait FnMut: FnOnce`)
* `Fn` requires `FnMut` (`trait Fn: FnMut`)

Because of this hierarchy, **all closures implement `FnOnce`**. If a function signature bounds a generic parameter to `F: FnOnce`, it dictates how the receiving function will *use* the closure (it promises to call it at most once). Consequently, a bound of `FnOnce` is the most permissive bound, accepting closures that are strictly `FnOnce`, as well as `FnMut` and `Fn` closures.

```rust theme={"dark"}
// This function accepts ANY closure, because all closures implement FnOnce.
fn execute_once<F>(closure: F)
where
    F: FnOnce(),
{
    closure();
}
```

## Distinction from the `move` Keyword

A common misconception is that the `move` keyword dictates whether a closure is `FnOnce`. The `move` keyword only dictates **how the closure captures variables** (forcing by-value capture instead of by-reference). It does not dictate **how the closure executes**.

A closure can use the `move` keyword to take ownership of a variable, but if it only reads or mutates that variable internally without moving it *out* of the closure body, it will still implement `Fn` or `FnMut`. `FnOnce` is strictly determined by whether the closure's execution consumes the captured state.

```rust theme={"dark"}
let data = String::from("data");

// Uses `move`, but does not consume `data` during execution.
// Therefore, it implements `Fn` (and by extension, `FnOnce`).
let print_closure = move || {
    println!("{}", data); 
};

print_closure();
print_closure(); // Valid, because it is not strictly FnOnce
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Rust Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
