@@ -415,12 +415,16 @@ f(Closure{s: s, t: &t});
415415```
416416
417417The 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.
424428
425429Composite types such as structs, tuples, and enums are always captured entirely,
426430not 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
448452to capture ` self ` by mutable reference. But since ` self.set ` is already
449453borrowed to iterate over, the code would not compile.
450454
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+
451483### Call traits and coercions
452484
453485Closure types all implement [ ` FnOnce ` ] , indicating that they can be called once
@@ -496,12 +528,12 @@ of cloning of the captured variables is left unspecified.
496528Because captures are often by reference, the following general rules arise:
497529
498530* 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 ` ] .
502534* 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.
505537
506538## Trait objects
507539
0 commit comments