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 implementsFnOnce
, 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.
Related videos on Youtube
Author by
Denilson Amorim
Updated on August 23, 2022Comments
-
Denilson Amorim over 1 year
What are the specific conditions for a closure to implement the
Fn
,FnMut
andFnOnce
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.-
Shepmaster almost 9 yearsHave you seen this recent great article on closures?
- When does a closure not implement the
-
nalply almost 9 yearsIf a closure only implements
FnOnce
, does this mean that it can be called only once? -
huon almost 9 years@nalply, yes, only once.
-
sleeparrow over 8 yearsI misread nalply's comment and it caused me some confusion. Future readers, please note that he said "if a closure only implements
FnOnce
". -
bluss over 7 yearsImplementation 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 over 3 yearsI 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 over 3 yearsA 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 about 2 yearswhat self are you talking about here? ||{} doesn't have a self. where does the self come from?
-
huon about 2 years@nikoss the
self
of the trait method. It is the struct that contains the captured variables (environment).