Skip to content

Commit a0c5784

Browse files
author
Alexis Hunt
committed
Add explanation of unique immutable borrows.
Also remove copy from the main list of permissible captures, since copy only occurs when `move` is specified.
1 parent 0041343 commit a0c5784

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

src/types.md

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,16 @@ f(Closure{s: s, t: &t});
415415
```
416416

417417
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.
424428

425429
Composite types such as structs, tuples, and enums are always captured entirely,
426430
not by individual fields. It may be necessary to borrow into a local variable in
@@ -448,6 +452,30 @@ If, instead, the closure were to use `self.vec` directly, then it would attempt
448452
to capture `self` by mutable reference. But since `self.set` is already
449453
borrowed 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+
let c = || { *x = true; };
466+
// The following line is an error:
467+
// let y = &x;
468+
c();
469+
```
470+
471+
In this case, borrowing `x` mutably is not possible, because `x` is not `mut`.
472+
But at the same time, borrowing `x` immutably would make the assignment illegal,
473+
because a `& &mut` reference may not be unique, so it cannot safely be used to
474+
modify a value. So a unique immutable borrow is used: it borrows `x` immutably,
475+
but like a mutable borrow, it must be unique. In the above example, uncommenting
476+
the declaration of `y` will produce an error because it would violate the
477+
uniqueness of the closure's borrow of `x`.
478+
451479
### Call traits and coercions
452480

453481
Closure types all implement [`FnOnce`], indicating that they can be called once

0 commit comments

Comments
 (0)