Type anonymity

Closures succinctly capture variables from enclosing scopes. Does this have
any consequences? It surely does. Observe how using a closure as a function
parameter requires generics, which is necessary because of how they are
defined:

  1. // `F` must be generic.
  2. fn apply<F>(f: F) where
  3. F: FnOnce() {
  4. f();
  5. }

When a closure is defined, the compiler implicitly creates a new
anonymous structure to store the captured variables inside, meanwhile
implementing the functionality via one of the traits: Fn, FnMut, or
FnOnce for this unknown type. This type is assigned to the variable which
is stored until calling.

Since this new type is of unknown type, any usage in a function will require
generics. However, an unbounded type parameter <T> would still be ambiguous
and not be allowed. Thus, bounding by one of the traits: Fn, FnMut, or
FnOnce (which it implements) is sufficient to specify its type.

  1. // `F` must implement `Fn` for a closure which takes no
  2. // inputs and returns nothing - exactly what is required
  3. // for `print`.
  4. fn apply<F>(f: F) where
  5. F: Fn() {
  6. f();
  7. }
  8. fn main() {
  9. let x = 7;
  10. // Capture `x` into an anonymous type and implement
  11. // `Fn` for it. Store it in `print`.
  12. let print = || println!("{}", x);
  13. apply(print);
  14. }

See also:

A thorough analysis, Fn, FnMut,
and FnOnce