@@ -365,30 +365,101 @@ x = bo(5,7);
365365## Closure types
366366
367367A [ 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:
369371
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+ }
372394
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+ ```
376402
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:
381404
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+ ```
388408
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.
392463
393464``` rust
394465let add = | x , y | x + y ;
@@ -400,6 +471,31 @@ let bo: Binop = add;
400471x = bo (5 ,7 );
401472```
402473
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+
403499## Trait objects
404500
405501A * trait object* is an opaque value of another type that implements a set of
@@ -593,6 +689,7 @@ impl Printable for String {
593689[ Clone ] : special-types-and-traits.html#clone
594690[ Send ] : special-types-and-traits.html#send
595691[ Sync ] : special-types-and-traits.html#sync
692+ [ derive ] : attributes.html#derive
596693[ `Vec<T>` ] : ../std/vec/struct.Vec.html
597694[ dynamically sized type ] : dynamically-sized-types.html
598695[ dynamically sized types ] : dynamically-sized-types.html
@@ -603,4 +700,4 @@ impl Printable for String {
603700[ auto traits ] : special-types-and-traits.html#auto-traits
604701[ object safe ] : items/traits.html#object-safety
605702[ 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