@@ -365,30 +365,99 @@ 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
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 and finally by move (or copy, for [ ` Copy ` ] types). It
411
+ will pick the first choice of these that allows the closure to compile. If the
412
+ ` move ` keyword is used, then all captures are by move or copy, regardless of
413
+ whether a borrow would work. The ` move ` keyword is usually used to allow the
414
+ closure to outlive the captured values, such as if the closure is being returned
415
+ or used to spawn a new thread.
416
+
417
+ Structs and tuples are always captured entirely, not by individual fields. It
418
+ may be necessary to borrow into a local variable in order to capture a single
419
+ field:
420
+
421
+ ``` rust
422
+ struct SetVec {
423
+ set : HashSet <u32 >,
424
+ vec : Vec <u32 >
425
+ }
426
+
427
+ impl Pair {
428
+ fn populate (& mut self ) {
429
+ let vec = & mut self . vec;
430
+ self . set. iter (). for_each (| & n | {
431
+ vec . push (n );
432
+ })
433
+ }
434
+ }
435
+ ```
436
+
437
+ If, instead, the closure were to use ` self.vec ` directly, then it would attempt
438
+ to capture ` self ` by mutable reference. But since ` self.set ` is already
439
+ borrowed to iterate over, the closure would not compile.
440
+
441
+ ### Call traits and coercions
442
+
443
+ Closure types all implement ` [FnOnce] ` , indicating that they can be called once
444
+ by consuming ownership of the closure. Additionally, some closures implement
445
+ more specific call traits:
446
+
447
+ * A closure which does not move out of any captured variables implements
448
+ ` [FnMut] ` , indicating that it can be called by mutable reference.
449
+
450
+ * A closure which does not mutate or move out of any captured variables
451
+ implements ` [Fn] ` , indicating that it can be called by shared reference.
452
+
453
+ > Note that ` move ` closures may still implement ` [Fn] ` or ` [FnMut] ` , even
454
+ > though they capture variables by move. This is because the traits
455
+ > implemented by a closure type are determined by what the closure does with
456
+ > captured values, not how it captures them.
457
+
458
+ In addition to the call traits, * non-capturing closures* ---those that don't
459
+ capture anything from their environment---can be coerced to function pointers
460
+ (` fn ` ) with the matching signature.
392
461
393
462
``` rust
394
463
let add = | x , y | x + y ;
@@ -400,6 +469,33 @@ let bo: Binop = add;
400
469
x = bo (5 ,7 );
401
470
```
402
471
472
+ ### Other traits
473
+
474
+ Closure types implement the following traits, if allowed to do so by the
475
+ captured values:
476
+
477
+ * ` [Sized] `
478
+ * ` [Send] `
479
+ * ` [Sync] `
480
+ * ` [Clone] `
481
+ * ` [Copy] `
482
+
483
+ ` [Sized] ` is always implemented (local variables are all sized, so all captured
484
+ values must be too). The rules for ` [Send] ` and ` [Sync] ` match those for normal
485
+ struct types, while ` [Clone] ` and ` [Copy] ` behave as if [ derived] [ derive ] . For
486
+ ` [Clone] ` , the order of cloning of the captured variables is left unspecified.
487
+
488
+ Because captures are often by reference, the following general rules arise:
489
+
490
+ * All closures are ` [Sized] ` .
491
+ * A closure is ` [Sync] ` if all values captured by mutable reference, move, or
492
+ copy are ` [Sync] ` .
493
+ * A closure is ` [Send] ` if all values captured by shared reference are ` [Sync] ` ,
494
+ and all values captured by mutable reference, move, or copy are ` [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 move or copy 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