@@ -415,12 +415,16 @@ f(Closure{s: s, t: &t});
415
415
```
416
416
417
417
The compiler prefers to capture a closed-over variable by immutable borrow,
418
- followed by mutable borrow, by copy, and finally by move. It will pick the first
419
- choice of these that allows the closure to compile. If the ` move ` keyword is
420
- used, then all captures are by move or copy, regardless of whether a borrow
421
- would work. The ` move ` keyword is usually used to allow the closure to outlive
422
- the captured values, such as if the closure is being returned or used to spawn a
423
- new thread.
418
+ followed by unique immutable borrow (see below), by mutable borrow, and finally
419
+ by move. It will pick the first choice of these that allows the closure to
420
+ compile. The choice is made only with regards to the contents of the closure
421
+ expression; the compiler does not take into account surrounding code, such as
422
+ the lifetimes of involved variables.
423
+
424
+ If the ` move ` keyword is used, then all captures are by move or, for ` Copy `
425
+ types, by copy, regardless of whether a borrow would work. The ` move ` keyword is
426
+ usually used to allow the closure to outlive the captured values, such as if the
427
+ closure is being returned or used to spawn a new thread.
424
428
425
429
Composite types such as structs, tuples, and enums are always captured entirely,
426
430
not by individual fields. It may be necessary to borrow into a local variable in
@@ -448,6 +452,34 @@ If, instead, the closure were to use `self.vec` directly, then it would attempt
448
452
to capture ` self ` by mutable reference. But since ` self.set ` is already
449
453
borrowed to iterate over, the code would not compile.
450
454
455
+ ### Unique immutable borrows in captures
456
+
457
+ Captures can occur by a special kind of borrow called a _ unique immutable
458
+ borrow_ , which cannot be used anywhere else in the language and cannot be
459
+ written out explicitly. It occurs when modifying the referent of a mutable
460
+ reference, as in the following example:
461
+
462
+ ``` rust
463
+ let mut b = false ;
464
+ let x = & mut b ;
465
+ {
466
+ let mut c = || { * x = true ; };
467
+ // The following line is an error:
468
+ // let y = &x;
469
+ c ();
470
+ }
471
+ let z = & x ;
472
+ ```
473
+
474
+ In this case, borrowing ` x ` mutably is not possible, because ` x ` is not ` mut ` .
475
+ But at the same time, borrowing ` x ` immutably would make the assignment illegal,
476
+ because a ` & &mut ` reference may not be unique, so it cannot safely be used to
477
+ modify a value. So a unique immutable borrow is used: it borrows ` x ` immutably,
478
+ but like a mutable borrow, it must be unique. In the above example, uncommenting
479
+ the declaration of ` y ` will produce an error because it would violate the
480
+ uniqueness of the closure's borrow of ` x ` ; the declaration of z is valid because
481
+ the closure's lifetime has expired at the end of the block, releasing the borrow.
482
+
451
483
### Call traits and coercions
452
484
453
485
Closure types all implement [ ` FnOnce ` ] , indicating that they can be called once
@@ -496,12 +528,12 @@ of cloning of the captured variables is left unspecified.
496
528
Because captures are often by reference, the following general rules arise:
497
529
498
530
* A closure is [ ` Sync ` ] if all captured variables are [ ` Sync ` ] .
499
- * A closure is [ ` Send ` ] if all variables captured by shared reference are
500
- [ ` Sync ` ] , and all values captured by mutable reference, copy, or move are
501
- [ ` Send ` ] .
531
+ * A closure is [ ` Send ` ] if all variables captured by non-unique immutable
532
+ reference are [ ` Sync ` ] , and all values captured by unique immutable or mutable
533
+ reference, copy, or move are [ ` Send ` ] .
502
534
* A closure is [ ` Clone ` ] or [ ` Copy ` ] if it does not capture any values by
503
- mutable reference, and if all values it captures by copy or move are
504
- [ ` Clone ` ] or [ ` Copy ` ] , respectively.
535
+ unique immutable or mutable reference, and if all values it captures by copy
536
+ or move are [ ` Clone ` ] or [ ` Copy ` ] , respectively.
505
537
506
538
## Trait objects
507
539
0 commit comments