Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. Fn / FnMut / FnOnce Traits

Fn / FnMut / FnOnce Traits

Rust closures implement one of three traits — Fn, FnMut, or FnOnce — depending on how they capture variables from the surrounding environment. When accepting a closure as a function argument, you specify its type using one of these trait bounds.

Syntax

// Fn — captures by immutable reference. Can be called any number of times.
fn call_fn<F: Fn() -> i32>(f: F) -> i32 { f() }

// FnMut — captures by mutable reference. Can be called repeatedly, but requires mut.
fn call_fnmut<F: FnMut() -> i32>(mut f: F) -> i32 { f() }

// FnOnce — takes ownership of captured values. Can only be called once.
fn call_fnonce<F: FnOnce() -> i32>(f: F) -> i32 { f() }

// Dynamic dispatch using dyn Fn()
fn call_dyn(f: &dyn Fn()) { f(); }

Trait Overview

TraitDescription
FnCaptures by immutable reference (&self). Can be called repeatedly. A superset of FnMut and FnOnce.
FnMutCaptures by mutable reference (&mut self). Can be called repeatedly. A superset of FnOnce.
FnOnceTakes ownership (self) of captured values. Can only be called once.
move closureMoves ownership of captured variables into the closure (commonly used when passing closures to threads).

Sample Code

fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
    f(x)
}

fn apply_mut<F: FnMut() -> i32>(mut f: F) -> i32 {
    f() + f()  // Called twice.
}

fn apply_once<F: FnOnce() -> String>(f: F) -> String {
    f()  // Called only once.
}

fn main() {
    // Fn — borrows the captured value immutably.
    let base = 10;
    let add_base = |x| x + base;  // Borrows base as &base.
    println!("Fn: {}", apply(add_base, 5));   // 15
    println!("Can be called again: {}", apply(|x| x * 2, 7));  // 14

    // FnMut — borrows the captured value mutably.
    let mut count = 0;
    let mut counter = || {
        count += 1;  // Borrows count as &mut count.
        count
    };
    println!("FnMut call 1: {}", counter());  // 1
    println!("FnMut call 2: {}", counter());  // 2
    println!("FnMut call 3: {}", counter());  // 3

    // apply_mut — calls the counter closure twice.
    let mut n = 0;
    let result = apply_mut(|| { n += 1; n });
    println!("apply_mut result: {}", result);  // 2

    // FnOnce — takes ownership, so it can only be called once.
    let name = String::from("Alice");
    let greet = move || format!("Hello, {}!", name);  // Takes ownership of name.
    println!("{}", apply_once(greet));  // Hello, Alice!
    // greet can no longer be called.

    // move closure — passing a closure to a thread
    let data = vec![1, 2, 3];
    let handle = std::thread::spawn(move || {
        // Moves ownership of data into the thread.
        println!("Inside thread: {:?}", data);
    });
    handle.join().unwrap();

    // Dynamic dispatch with dyn Fn()
    let funcs: Vec<Box<dyn Fn(i32) -> i32>> = vec![
        Box::new(|x| x + 1),
        Box::new(|x| x * 2),
        Box::new(|x| x * x),
    ];
    for f in &funcs {
        print!("{} ", f(3));  // 4 6 9
    }
    println!();
}

Notes

Rust closures capture variables from the surrounding scope in one of three ways: immutable borrow, mutable borrow, or move (transfer of ownership). Each corresponds to the Fn, FnMut, or FnOnce trait. These traits form a hierarchy: a closure that implements Fn automatically implements FnMut and FnOnce as well.

Using Box<dyn Fn()> as a parameter type allows you to store closures of different concrete types in the same collection (dynamic dispatch). When performance matters, use generic bounds like <F: Fn()> for static dispatch, which enables inlining by the compiler.

When passing a closure to a thread, you must use move to transfer ownership of captured variables. See std::thread::spawn() / join() for details.

If you find any errors or copyright issues, please .