1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
//! Provides two macros for more powerful closure captures.
//!
//! # Background
//!
//! Closures in Rust, despite being extremely powerful, do not offer many options for modifying the
//! way in which they capture their output. A particular pain point is often needing to `.clone()`
//! an `Arc<T>` or `Rc<T>` for the closure to capture. This pattern does not compile:
//! ```compile_fail
//! # use std::rc::Rc;
//! fn needs_static<T: FnOnce() -> i32 + 'static>(f: T) -> i32 {
//! f()
//! }
//!
//! let local: Rc<i32> = Rc::new(1);
//! // Try and capture a clone of the `Rc`
//! let mut f = || {
//! let in_closure = local.clone();
//! *in_closure.as_ref()
//! };
//! // `f` is not `'static`!
//! assert_eq!(needs_static(f), 1);
//! // `local` has not been captured!
//! assert_eq!(*local.as_ref(), 1);
//! ```
//!
//! That's because when writing `local.clone()` in the body of the closure, that `clone` call is not
//! executed until the closure is called; this means that the closure is actually capturing a
//! `&local` and so it's not `'static`! Making `f` a `move` closure does not fix this, since then
//! `local` will be captured by value, and the later `local.as_ref()` statement will fail. What we
//! want instead is for the `.clone()` to be executed when the closure is created:
//! ```
//! # use std::rc::Rc;
//! fn needs_static<T: FnOnce() -> i32 + 'static>(f: T) -> i32 {
//! f()
//! }
//!
//! let local: Rc<i32> = Rc::new(1);
//! // Actually capture a clone of the `Rc`
//! let cloned = local.clone();
//! let f = move || {
//! let in_closure = cloned;
//! *in_closure.as_ref()
//! };
//! // `f` is now `'static`!
//! assert_eq!(needs_static(f), 1);
//! // `local` has not been captured!
//! assert_eq!(*local.as_ref(), 1);
//! ```
//!
//! # Usage
//!
//! The `captures::capture` and `captures::capture_only` macros are invoked with a comma-seperated
//! list of "capture directives" and finally a closure expression. One example of a capture
//! directive is the `clone x` directive, which indicates that a clone of `x` should be captured in
//! place of `x`. As such, the example above can be re-written to:
//! ```
//! # use std::rc::Rc;
//! use captures::capture;
//! fn needs_static<T: FnOnce() -> i32 + 'static>(f: T) -> i32 {
//! f()
//! }
//!
//! let local: Rc<i32> = Rc::new(1);
//! // Actually capture a clone of the `Rc`
//! let f = capture!(clone local,
//! move || {
//! let in_closure = local;
//! *in_closure.as_ref()
//! }
//! );
//! // `f` is still `'static`!
//! assert_eq!(needs_static(f), 1);
//! // `local` has not been captured!
//! assert_eq!(*local.as_ref(), 1);
//! ```
//!
//! ## Capture Directives
//!
//! These capture directives are currently supported:
//!
//! - `clone x` captures a clone of `x`.
//! - `with x = expr` captures a value `x` that is computed from `expr`.
//! - `all x` captures all of `x`. Beginning in Rust 2021, writing `x.y` in your closure would lead
//! to only the `y` field of `x` being captured. Specifying `all x` causes all of `x` to be
//! captured instead. This does not influence whether `x` is captured by value or by reference -
//! if the closure is a `move` closure, it will still be captured by value, and if it is a
//! non-`move` closure, the compiler's standard inference algorithm is allowed to make the
//! decision.
// - `rename x y` captures `y` outside the closure, but renames it to `x` and allows it to be
// accessed as `x` inside the body of the closure. This does not force all of `y` to be
// captured, and it does not influence whether `y` or any of its fields are captured by value or
// by reference. (not yet supported)
//!
//! To avoid surprises and compilation errors, if you specify a `clone` or `with` directive, then
//! this macro will turn your closure into a move closure if it was not one already. Because of
//! this, if your closure is a `move` closure - either because you explicitly marked it as such or
//! because you used a `with` or `clone` directive - then you may additionally specify these
//! directives:
// FIXME: Decide if its not better to require that the user specify the `move` instead of
// "inferring" it.
//!
//! - `ref x` captures `x` by immutable reference.
//! - `ref mut x` captures `x` by mutable reference.
//!
//! The `x` in all of these directives must simply be the name of a local variable. Some more
//! complicated things may be supported in the future. There is at the moment also no support for
//! combining directives. I will add this once I figure out a pretty and consistent way to do it.
//!
//! ## Mutability
//!
//! In Rust, captured variables that are captured by value inherit the mutability of the value they
//! reference. For example,
//! ```compile_fail
//! let a = 1; // immutable
//! let _ = move || {
//! a += 1;
//! a
//! };
//! ```
//! does not compile, but if `a` is marked as mutable
//! ```
//! let mut a = 1; // now mutable
//! let _ = move || {
//! a += 1;
//! a
//! };
//! ```
//! it does.
//!
//! Unfortunately, this crate does not have the necessary information to reproduce this behavior in
//! general. `clone` and `with` directives create new variables for which it is not clear what their
//! mutability should be. The current policy is for all of them to default to immutable. This may be
//! changed in the future (obviously respecting semver) if it is determined that this is not the
//! best option. If you do want these values to be mutable, you can request that by prefixing the
//! variable with a `mut`. For example,
//!
//! ```compile_fail
//! # use captures::capture;
//! let mut v = vec![1, 2]; // despite being mutable here
//! let _ = capture!(clone v, || {
//! v.push(3); // we cannot push to `v`, since it is not mutable
//! v
//! });
//! ```
//! We can fix this via:
//! ```
//! # use captures::capture;
//! let mut v = vec![1, 2];
//! let _ = capture!(clone mut v, || {
//! v.push(3); // we can push now
//! v
//! });
//! ```
//! This will still emit a warning because the mutability of the variable `v` outside the closure is
//! unused. Writing instead `let v = vec![1, 2];` would continue to compile and the warning would not
//! be emitted.
//!
//! `all` directives are not affected by this. Variables captured under such a directive, if
//! captured by value, correctly inherit their mutability. As such, the `mut` prefix is not
//! supported on these directives.
//!
//! # [`capture_only`]
//!
//! The `capture_only` macro behaves exactly like the `capture` macro, with the exception that it
//! additionally prevents any variables that do not have an associated capture directive from
//! being captured. For example,
//! ```compile_fail
//! # use captures::capture_only;
//! let a = 1;
//! let mut b = 10;
//! let mut f = capture_only!(all a, || {
//! b += 1; // error
//! a + 1
//! });
//! assert_eq!(f(), 2);
//! assert_eq!(b, 11);
//! ```
//! does not compile, with an error message indicating that there is no local variable `b`.
//! Switching `capture_only` to `capture` would allow the above code to compile. If you would like
//! to indicate that `b` may also be captured, but do not want to add any restrictions on how, you
//! can add an `all` directive:
//! ```
//! # use captures::capture_only;
//! let a = 1;
//! let mut b = 10;
//! let mut f = capture_only!(all a, all b, || {
//! b += 1; // compiles
//! a + 1
//! });
//! assert_eq!(f(), 2);
//! assert_eq!(b, 11);
//! ```
//!
use TokenStream;
use quote;
/// Takes a place with type having `.set_span(_)` and `.span()` methods
use *;
use *;
/// Allows specifying how a closure should capture variables.
///
/// See the [crate level documentation][`crate`] for more info.
/// Allows specifying how a closure should capture variables.
///
/// See the [crate level documentation][`crate`] for more info.