@@ -365,30 +365,101 @@ x = bo(5,7);
365
365
## Closure types
366
366
367
367
A [ closure expression] produces a closure value with a unique, anonymous type
368
- that cannot be written out.
368
+ that cannot be written out. A closure type is approximately equivalent to a
369
+ struct which contains the captured variables. For instance, the following
370
+ closure:
369
371
370
- Depending on the requirements of the closure, its type implements one or
371
- more of the closure traits:
372
+ ``` rust
373
+ fn f <F : FnOnce () -> String > (g : F ) {
374
+ println! (" {}" , g ());
375
+ }
376
+
377
+ let mut s = String :: from (" foo" );
378
+ let t = String :: from (" bar" );
379
+
380
+ f (|| {
381
+ s += & * t ;
382
+ s
383
+ });
384
+ // Prints "foobar".
385
+ ```
386
+
387
+ generates a closure type roughly like the following:
388
+
389
+ ``` rust,ignore
390
+ struct Closure<'a> {
391
+ s : String,
392
+ t : &'a String,
393
+ }
372
394
373
- * ` FnOnce `
374
- : The closure can be called once. A closure called as ` FnOnce ` can move out
375
- of its captured values.
395
+ impl<'a> (FnOnce() -> String) for Closure<'a> {
396
+ fn call_once(self) -> String {
397
+ self.s += &*self.t;
398
+ self.s
399
+ }
400
+ }
401
+ ```
376
402
377
- * ` FnMut `
378
- : The closure can be called multiple times as mutable. A closure called as
379
- ` FnMut ` can mutate values from its environment. ` FnMut ` inherits from
380
- ` FnOnce ` (i.e. anything implementing ` FnMut ` also implements ` FnOnce ` ).
403
+ so that the call to ` f ` works as if it were:
381
404
382
- * ` Fn ` : The closure can be called multiple times through a shared reference. A
383
- closure called as ` Fn ` can neither move out from nor mutate captured
384
- variables, but read-only access to such values is allowed. Using ` move ` to
385
- capture variables by value is allowed so long as they aren't mutated or
386
- moved in the body of the closure. ` Fn ` inherits from ` FnMut ` , which itself
387
- inherits from ` FnOnce ` .
405
+ ``` rust,ignore
406
+ f(Closure{s: s, t: &t});
407
+ ```
388
408
389
- Closures that don't use anything from their environment, called * non-capturing
390
- closures* , can be coerced to function pointers (` fn ` ) with the matching
391
- signature. To adopt the example from the section above:
409
+ The compiler prefers to capture a closed-over variable by immutable borrow,
410
+ followed by mutable borrow, by copy, and finally by move. It will pick the first
411
+ choice of these that allows the closure to compile. If the ` move ` keyword is
412
+ used, then all captures are by move or copy, regardless of whether a borrow
413
+ would work. The ` move ` keyword is usually used to allow the closure to outlive
414
+ the captured values, such as if the closure is being returned or used to spawn a
415
+ new thread.
416
+
417
+ Composite types such as structs, tuples, and enums are always captured entirely,
418
+ not by individual fields. It may be necessary to borrow into a local variable in
419
+ order to capture a single field:
420
+
421
+ ``` rust
422
+ # use std :: collections :: HashSet ;
423
+ #
424
+ struct SetVec {
425
+ set : HashSet <u32 >,
426
+ vec : Vec <u32 >
427
+ }
428
+
429
+ impl SetVec {
430
+ fn populate (& mut self ) {
431
+ let vec = & mut self . vec;
432
+ self . set. iter (). for_each (| & n | {
433
+ vec . push (n );
434
+ })
435
+ }
436
+ }
437
+ ```
438
+
439
+ If, instead, the closure were to use ` self.vec ` directly, then it would attempt
440
+ to capture ` self ` by mutable reference. But since ` self.set ` is already
441
+ borrowed to iterate over, the code would not compile.
442
+
443
+ ### Call traits and coercions
444
+
445
+ Closure types all implement ` [FnOnce] ` , indicating that they can be called once
446
+ by consuming ownership of the closure. Additionally, some closures implement
447
+ more specific call traits:
448
+
449
+ * A closure which does not move out of any captured variables implements
450
+ ` [FnMut] ` , indicating that it can be called by mutable reference.
451
+
452
+ * A closure which does not mutate or move out of any captured variables
453
+ implements ` [Fn] ` , indicating that it can be called by shared reference.
454
+
455
+ > Note: ` move ` closures may still implement ` [Fn] ` or ` [FnMut] ` , even though
456
+ > they capture variables by move. This is because the traits implemented by a
457
+ > closure type are determined by what the closure does with captured values, not
458
+ > how it captures them.
459
+
460
+ * Non-capturing closures* are closures that don't capture anything from their
461
+ environment. They can be coerced to function pointers (` fn ` ) with the matching
462
+ signature.
392
463
393
464
``` rust
394
465
let add = | x , y | x + y ;
@@ -400,6 +471,31 @@ let bo: Binop = add;
400
471
x = bo (5 ,7 );
401
472
```
402
473
474
+ ### Other traits
475
+
476
+ All closure types implement ` [Sized] ` . Additionally, closure types implement the
477
+ following traits if allowed to do so by the types of the captures it stores:
478
+
479
+ * ` [Clone] `
480
+ * ` [Copy] `
481
+ * ` [Sync] `
482
+ * ` [Send] `
483
+
484
+ The rules for ` [Send] ` and ` [Sync] ` match those for normal struct types, while
485
+ ` [Clone] ` and ` [Copy] ` behave as if [ derived] [ derive ] . For ` [Clone] ` , the order
486
+ of cloning of the captured variables is left unspecified.
487
+
488
+ Because captures are often by reference, the following general rules arise:
489
+
490
+ * A closure is ` [Sync] ` if all variables captured by mutable reference, copy, or
491
+ move are ` [Sync] ` .
492
+ * A closure is ` [Send] ` if all variables captured by shared reference are
493
+ ` [Sync] ` , and all values captured by mutable reference, copy, or move are
494
+ ` [Send] ` .
495
+ * A closure is ` [Clone] ` or ` [Copy] ` if it does not capture any values by
496
+ mutable reference, and if all values it captures by copy or move are ` [Clone] `
497
+ or ` [Copy] ` , respectively.
498
+
403
499
## Trait objects
404
500
405
501
A * trait object* is an opaque value of another type that implements a set of
@@ -593,6 +689,7 @@ impl Printable for String {
593
689
[ Clone ] : special-types-and-traits.html#clone
594
690
[ Send ] : special-types-and-traits.html#send
595
691
[ Sync ] : special-types-and-traits.html#sync
692
+ [ derive ] : attributes.html#derive
596
693
[ `Vec<T>` ] : ../std/vec/struct.Vec.html
597
694
[ dynamically sized type ] : dynamically-sized-types.html
598
695
[ dynamically sized types ] : dynamically-sized-types.html
@@ -603,4 +700,4 @@ impl Printable for String {
603
700
[ auto traits ] : special-types-and-traits.html#auto-traits
604
701
[ object safe ] : items/traits.html#object-safety
605
702
[ issue 47010 ] : https://github.com/rust-lang/rust/issues/47010
606
- [ issue 33140 ] : https://github.com/rust-lang/rust/issues/33140
703
+ [ issue 33140 ] : https://github.com/rust-lang/rust/issues/33140
0 commit comments