When does a closure implement Fn, FnMut and FnOnce?

36,502

The traits each represent more and more restrictive properties about closures/functions, indicated by the signatures of their call_... method, and particularly the type of self:

  • FnOnce (self) are functions that can be called once
  • FnMut (&mut self) are functions that can be called if they have &mut access to their environment
  • Fn (&self) are functions that can be called if they only have & access to their environment

A closure |...| ... will automatically implement as many of those as it can.

  • All closures implement FnOnce: a closure that can't be called once doesn't deserve the name. Note that if a closure only implements FnOnce, it can be called only once.
  • Closures that don't move out of their captures implement FnMut, allowing them to be called more than once (if there is unaliased access to the function object).
  • Closures that don't need unique/mutable access to their captures implement Fn, allowing them to be called essentially everywhere.

These restrictions follow directly from the type of self and the "desugaring" of closures into structs; described in my blog post Finding Closure in Rust.

For information on closures, see Closures: Anonymous Functions that Can Capture Their Environment in The Rust Programming Language.

Share:
36,502

Related videos on Youtube

Denilson Amorim
Author by

Denilson Amorim

Updated on August 23, 2022

Comments

  • Denilson Amorim
    Denilson Amorim over 1 year

    What are the specific conditions for a closure to implement the Fn, FnMut and FnOnce traits?

    That is:

    • When does a closure not implement the FnOnce trait?
    • When does a closure not implement the FnMut trait?
    • When does a closure not implement the Fn trait?

    For instance, mutating the state of the closure on it's body makes the compiler not implement Fn on it.

  • nalply
    nalply almost 9 years
    If a closure only implements FnOnce, does this mean that it can be called only once?
  • huon
    huon almost 9 years
    @nalply, yes, only once.
  • sleeparrow
    sleeparrow over 8 years
    I misread nalply's comment and it caused me some confusion. Future readers, please note that he said "if a closure only implements FnOnce".
  • bluss
    bluss over 7 years
    Implementation detail: will automatically implement as many of those as it can. is not entirely true, it will implement them automatically if it seems to be needed. You can detect a missing Fn-impl for a closure that was used for an FnMut argument using specialization. This is bug github.com/rust-lang/rust/issues/26085
  • Paul Razvan Berg
    Paul Razvan Berg over 3 years
    I still struggle to understand how all closures implement FnOnce even if they can be called multiple times. The name for this trait is confusing.
  • hjfreyer
    hjfreyer over 3 years
    A couple ways to think about it: 1. The "Once" in FnOnce refers to an upper bound on how many times the caller will invoke it, not how many times it can be invoked. 2. You can always convert a closure that can be called many times into a closure that can only be called once: simply throw away any memory associated with the closure after the first call. But you can't convert it back the other way.
  • nikoss
    nikoss about 2 years
    what self are you talking about here? ||{} doesn't have a self. where does the self come from?
  • huon
    huon about 2 years
    @nikoss the self of the trait method. It is the struct that contains the captured variables (environment).