Skip to content

Commit

Permalink
Merge pull request #1281 from illiteratewriter/closures-generics
Browse files Browse the repository at this point in the history
Add reference to Generics
  • Loading branch information
marioidival committed Oct 14, 2019
2 parents ce9965b + 0913ff6 commit 6f0690b
Showing 1 changed file with 17 additions and 14 deletions.
31 changes: 17 additions & 14 deletions src/fn/closures/input_parameters.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
# 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,
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.
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
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
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
In the following example, try swapping the usage of `Fn`, `FnMut`, and
`FnOnce` to see what happens:

```rust,editable
// A function which takes a closure as an argument and calls it.
// <F> denotes that F is a "Generic type parameter"
fn apply<F>(f: F) where
// The closure takes no input and returns nothing.
F: FnOnce() {
Expand Down Expand Up @@ -81,9 +82,11 @@ fn main() {

### See also:

[`std::mem::drop`][drop], [`Fn`][fn], [`FnMut`][fnmut], and [`FnOnce`][fnonce]
[`std::mem::drop`][drop], [`Fn`][fn], [`FnMut`][fnmut], [Generics][generics], [where][where] and [`FnOnce`][fnonce]

[drop]: https://doc.rust-lang.org/std/mem/fn.drop.html
[fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html
[fnmut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html
[fnonce]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html
[generics]: ../../generics.md
[where]: ../../generics/where.md

0 comments on commit 6f0690b

Please sign in to comment.