]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/types/closure.md
New upstream version 1.55.0+dfsg1
[rustc.git] / src / doc / reference / src / types / closure.md
CommitLineData
13cf67c4
XL
1# Closure types
2
3A [closure expression] produces a closure value with a unique, anonymous type
4that cannot be written out. A closure type is approximately equivalent to a
5struct which contains the captured variables. For instance, the following
6closure:
7
8```rust
9fn f<F : FnOnce() -> String> (g: F) {
10 println!("{}", g());
11}
12
13let mut s = String::from("foo");
14let t = String::from("bar");
15
16f(|| {
3dfed10e 17 s += &t;
13cf67c4
XL
18 s
19});
20// Prints "foobar".
21```
22
23generates a closure type roughly like the following:
24
60c5eb7d 25<!-- ignore: simplified, requires unboxed_closures, fn_traits -->
13cf67c4
XL
26```rust,ignore
27struct Closure<'a> {
28 s : String,
29 t : &'a String,
30}
31
60c5eb7d
XL
32impl<'a> FnOnce<()> for Closure<'a> {
33 type Output = String;
13cf67c4
XL
34 fn call_once(self) -> String {
35 self.s += &*self.t;
36 self.s
37 }
38}
39```
40
41so that the call to `f` works as if it were:
42
60c5eb7d 43<!-- ignore: continuation of above -->
13cf67c4
XL
44```rust,ignore
45f(Closure{s: s, t: &t});
46```
47
48## Capture modes
49
50The compiler prefers to capture a closed-over variable by immutable borrow,
51followed by unique immutable borrow (see below), by mutable borrow, and finally
136023e0
XL
52by move. It will pick the first choice of these that is compatible with how the
53captured variable is used inside the closure body. The compiler does not take
54surrounding code into account, such as the lifetimes of involved variables, or
55of the closure itself.
13cf67c4
XL
56
57If the `move` keyword is used, then all captures are by move or, for `Copy`
58types, by copy, regardless of whether a borrow would work. The `move` keyword is
59usually used to allow the closure to outlive the captured values, such as if the
60closure is being returned or used to spawn a new thread.
61
62Composite types such as structs, tuples, and enums are always captured entirely,
63not by individual fields. It may be necessary to borrow into a local variable in
64order to capture a single field:
65
66```rust
67# use std::collections::HashSet;
68#
69struct SetVec {
70 set: HashSet<u32>,
71 vec: Vec<u32>
72}
73
74impl SetVec {
75 fn populate(&mut self) {
76 let vec = &mut self.vec;
77 self.set.iter().for_each(|&n| {
78 vec.push(n);
79 })
80 }
81}
82```
83
84If, instead, the closure were to use `self.vec` directly, then it would attempt
85to capture `self` by mutable reference. But since `self.set` is already
86borrowed to iterate over, the code would not compile.
87
88## Unique immutable borrows in captures
89
90Captures can occur by a special kind of borrow called a _unique immutable
91borrow_, which cannot be used anywhere else in the language and cannot be
92written out explicitly. It occurs when modifying the referent of a mutable
93reference, as in the following example:
94
95```rust
96let mut b = false;
97let x = &mut b;
98{
99 let mut c = || { *x = true; };
100 // The following line is an error:
101 // let y = &x;
102 c();
103}
104let z = &x;
105```
106
107In this case, borrowing `x` mutably is not possible, because `x` is not `mut`.
108But at the same time, borrowing `x` immutably would make the assignment illegal,
109because a `& &mut` reference may not be unique, so it cannot safely be used to
110modify a value. So a unique immutable borrow is used: it borrows `x` immutably,
111but like a mutable borrow, it must be unique. In the above example, uncommenting
112the declaration of `y` will produce an error because it would violate the
113uniqueness of the closure's borrow of `x`; the declaration of z is valid because
114the closure's lifetime has expired at the end of the block, releasing the borrow.
115
116## Call traits and coercions
117
118Closure types all implement [`FnOnce`], indicating that they can be called once
119by consuming ownership of the closure. Additionally, some closures implement
120more specific call traits:
121
122* A closure which does not move out of any captured variables implements
123 [`FnMut`], indicating that it can be called by mutable reference.
124
125* A closure which does not mutate or move out of any captured variables
126 implements [`Fn`], indicating that it can be called by shared reference.
127
128> Note: `move` closures may still implement [`Fn`] or [`FnMut`], even though
129> they capture variables by move. This is because the traits implemented by a
130> closure type are determined by what the closure does with captured values,
131> not how it captures them.
132
133*Non-capturing closures* are closures that don't capture anything from their
3dfed10e
XL
134environment. They can be coerced to function pointers (e.g., `fn()`)
135with the matching signature.
13cf67c4
XL
136
137```rust
138let add = |x, y| x + y;
139
140let mut x = add(5,7);
141
142type Binop = fn(i32, i32) -> i32;
143let bo: Binop = add;
144x = bo(5,7);
145```
146
147## Other traits
148
149All closure types implement [`Sized`]. Additionally, closure types implement the
150following traits if allowed to do so by the types of the captures it stores:
151
152* [`Clone`]
153* [`Copy`]
154* [`Sync`]
155* [`Send`]
156
157The rules for [`Send`] and [`Sync`] match those for normal struct types, while
158[`Clone`] and [`Copy`] behave as if [derived]. For [`Clone`], the order of
159cloning of the captured variables is left unspecified.
160
161Because captures are often by reference, the following general rules arise:
162
163* A closure is [`Sync`] if all captured variables are [`Sync`].
164* A closure is [`Send`] if all variables captured by non-unique immutable
165 reference are [`Sync`], and all values captured by unique immutable or mutable
166 reference, copy, or move are [`Send`].
167* A closure is [`Clone`] or [`Copy`] if it does not capture any values by
168 unique immutable or mutable reference, and if all values it captures by copy
169 or move are [`Clone`] or [`Copy`], respectively.
170
416331ca
XL
171[`Clone`]: ../special-types-and-traits.md#clone
172[`Copy`]: ../special-types-and-traits.md#copy
173[`FnMut`]: ../../std/ops/trait.FnMut.html
174[`FnOnce`]: ../../std/ops/trait.FnOnce.html
175[`Fn`]: ../../std/ops/trait.Fn.html
176[`Send`]: ../special-types-and-traits.md#send
177[`Sized`]: ../special-types-and-traits.md#sized
178[`Sync`]: ../special-types-and-traits.md#sync
179[closure expression]: ../expressions/closure-expr.md
180[derived]: ../attributes/derive.md