As input parameters

While Rust chooses how to capture variables on the fly mostly without type
annotation, this ambiguity is not allowed when writing functions. When
taking a closure as an input parameter, the closure’s complete type must be
annotated using one of a few traits. In order of decreasing restriction,
they are:

  • Fn: the closure captures by reference (&T)
  • FnMut: the closure captures by mutable reference (&mut T)
  • FnOnce: the closure captures by value (T)

On a variable-by-variable basis, the compiler will capture variables in the
least restrictive manner possible.

For instance, consider a parameter annotated as FnOnce. This specifies
that the closure may capture by &T, &mut T, or T, but the compiler
will ultimately choose based on how the captured variables are used in the
closure.

This is because if a move is possible, then any type of borrow should also
be possible. Note that the reverse is not true. If the parameter is
annotated as Fn, then capturing variables by &mut T or T are not
allowed.

In the following example, try swapping the usage of Fn, FnMut, and
FnOnce to see what happens:

  1. // A function which takes a closure as an argument and calls it.
  2. fn apply<F>(f: F) where
  3. // The closure takes no input and returns nothing.
  4. F: FnOnce() {
  5. // ^ TODO: Try changing this to `Fn` or `FnMut`.
  6. f();
  7. }
  8. // A function which takes a closure and returns an `i32`.
  9. fn apply_to_3<F>(f: F) -> i32 where
  10. // The closure takes an `i32` and returns an `i32`.
  11. F: Fn(i32) -> i32 {
  12. f(3)
  13. }
  14. fn main() {
  15. use std::mem;
  16. let greeting = "hello";
  17. // A non-copy type.
  18. // `to_owned` creates owned data from borrowed one
  19. let mut farewell = "goodbye".to_owned();
  20. // Capture 2 variables: `greeting` by reference and
  21. // `farewell` by value.
  22. let diary = || {
  23. // `greeting` is by reference: requires `Fn`.
  24. println!("I said {}.", greeting);
  25. // Mutation forces `farewell` to be captured by
  26. // mutable reference. Now requires `FnMut`.
  27. farewell.push_str("!!!");
  28. println!("Then I screamed {}.", farewell);
  29. println!("Now I can sleep. zzzzz");
  30. // Manually calling drop forces `farewell` to
  31. // be captured by value. Now requires `FnOnce`.
  32. mem::drop(farewell);
  33. };
  34. // Call the function which applies the closure.
  35. apply(diary);
  36. // `double` satisfies `apply_to_3`'s trait bound
  37. let double = |x| 2 * x;
  38. println!("3 doubled: {}", apply_to_3(double));
  39. }

See also:

std::mem::drop, Fn, FnMut, and FnOnce