@@ -365,30 +365,99 @@ 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
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 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.
392461
393462``` rust
394463let add = | x , y | x + y ;
@@ -400,6 +469,33 @@ let bo: Binop = add;
400469x = bo (5 ,7 );
401470```
402471
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+
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