I'm not sure which article you're referring to, so in case it didn't mention it -- FnMut
closures also implement FnOnce
, and Fn
closures also implement both FnMut
and FnOnce
. These relationships are expressed as sub/supertrait relationships. The closures may also be Copy
, Clone
, Send
, and Sync
depending on what is captured.
More documentation here and here.
In practice, when you have a function that takes a closure, you'll bind the argument on one the traits -- usually the least "flexible" version you need (FnOnce
, FnMut
, or Fn
) in order to accept the most closures. Usually this is the only thing you need to think about, and it will just work. Sometimes you need to add extra bounds, like + Send
(if you're sending it to another thread, say).
When you call the closure, the most flexible version will be used -- so if you bind on FnMut
, you'll call FnMut
, not FnOnce
. (FnOnce
is still available because of the supertrait relationship. This can matter if you need to pass the closure on to something with a different bound. But again you'll almost never need to think about it.) The difference between Fn
and FnMut
only matters if you're extending the borrow of the closure by keeping a return value with a lifetime around.
And now for a nit that you will probably never run into.
When executed in different contexts, the body executes the same, but if you call something only known (e.g. by trait bounds) to be a FnOnce
, it will consume the closure. If you try to use the closure after that, it will either fail or -- if the closure is (known to be) Copy
-- execute a copy of the closure. This latter case may be surprising in the case of closure with state.
You'll almost surely never run into this directly because you'll almost surely never write a FnOnce + Copy
bound.
However, a similar situation can happen when you create a closure and pass it to a function that takes the closure by value -- you may unwittingly pass a copy of the closure in some cases.
Example.