1
1
# Closure types
2
2
3
+ r[ type.closure]
4
+
3
5
A [ closure expression] produces a closure value with a unique, anonymous type
4
6
that cannot be written out. A closure type is approximately equivalent to a
5
7
struct which contains the captured variables. For instance, the following
@@ -47,21 +49,27 @@ f(Closure{s: s, t: &t});
47
49
48
50
## Capture modes
49
51
52
+ r[ type.closure.capture]
53
+
54
+ r[ type.closure.capture.order]
50
55
The compiler prefers to capture a closed-over variable by immutable borrow,
51
56
followed by unique immutable borrow (see below), by mutable borrow, and finally
52
57
by move. It will pick the first choice of these that is compatible with how the
53
58
captured variable is used inside the closure body. The compiler does not take
54
59
surrounding code into account, such as the lifetimes of involved variables, or
55
60
of the closure itself.
56
61
62
+ r[ type.closure.capture.move]
57
63
If the ` move ` keyword is used, then all captures are by move or, for ` Copy `
58
64
types, by copy, regardless of whether a borrow would work. The ` move ` keyword is
59
65
usually used to allow the closure to outlive the captured values, such as if the
60
66
closure is being returned or used to spawn a new thread.
61
67
68
+ r[ type.closure.capture.composite]
62
69
Composite types such as structs, tuples, and enums are always captured entirely,
63
70
not by individual fields. It may be necessary to borrow into a local variable in
64
71
order to capture a single field:
72
+ <!-- editor note, not true in Edition 2021 -->
65
73
66
74
``` rust
67
75
# use std :: collections :: HashSet ;
@@ -87,6 +95,8 @@ borrowed to iterate over, the code would not compile.
87
95
88
96
## Unique immutable borrows in captures
89
97
98
+ r[ type.closure.unique-immutable]
99
+
90
100
Captures can occur by a special kind of borrow called a _ unique immutable
91
101
borrow_ , which cannot be used anywhere else in the language and cannot be
92
102
written out explicitly. It occurs when modifying the referent of a mutable
@@ -115,13 +125,18 @@ the closure's lifetime has expired at the end of the block, releasing the borrow
115
125
116
126
## Call traits and coercions
117
127
128
+ r[ type.closure.call]
129
+
130
+ r[ type.closure.call.intro]
118
131
Closure types all implement [ ` FnOnce ` ] , indicating that they can be called once
119
132
by consuming ownership of the closure. Additionally, some closures implement
120
133
more specific call traits:
121
134
135
+ r[ type.closure.call.fn-mut]
122
136
* A closure which does not move out of any captured variables implements
123
137
[ ` FnMut ` ] , indicating that it can be called by mutable reference.
124
138
139
+ r[ type.closure.call.fn]
125
140
* A closure which does not mutate or move out of any captured variables
126
141
implements [ ` Fn ` ] , indicating that it can be called by shared reference.
127
142
@@ -130,6 +145,7 @@ more specific call traits:
130
145
> closure type are determined by what the closure does with captured values,
131
146
> not how it captures them.
132
147
148
+ r[ type.closure.non-capturing]
133
149
* Non-capturing closures* are closures that don't capture anything from their
134
150
environment. They can be coerced to function pointers (e.g., ` fn() ` )
135
151
with the matching signature.
@@ -146,6 +162,9 @@ x = bo(5,7);
146
162
147
163
## Other traits
148
164
165
+ r[ type.closure.traits]
166
+
167
+ r[ type.closure.traits.intro]
149
168
All closure types implement [ ` Sized ` ] . Additionally, closure types implement the
150
169
following traits if allowed to do so by the types of the captures it stores:
151
170
@@ -154,6 +173,7 @@ following traits if allowed to do so by the types of the captures it stores:
154
173
* [ ` Sync ` ]
155
174
* [ ` Send ` ]
156
175
176
+ r[ type.closure.traits.behavior]
157
177
The rules for [ ` Send ` ] and [ ` Sync ` ] match those for normal struct types, while
158
178
[ ` Clone ` ] and [ ` Copy ` ] behave as if [ derived] . For [ ` Clone ` ] , the order of
159
179
cloning of the captured variables is left unspecified.
0 commit comments