Skip to content

Commit 151b109

Browse files
committed
Revise ...discriminants.slice-patterns-* rules
The section here stated: > Matching against a slice pattern that needs to inspect the length of > the scrutinee performs a read of the pointer value in order to fetch > the length. The read will cause the closure to borrow the relevant > place by `ImmBorrow`. It then goes on to state exceptions for arrays matched against slice patterns and slice patterns containing only a rest pattern. As we saw in an earlier commit, it's better to not lean on the reader to infer the "relevant place" or when the length needs to be inspected. Let's elaborate those details and state the full rule in one go, upfront, and then state a separate guarantee that matching an array against a slice pattern does not do a read. We'll also fix a typo, add rule identifiers, fix a statement in an example about what exactly is captured, and tighten up the examples generally.
1 parent 1719573 commit 151b109

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

src/types/closure.md

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -365,38 +365,42 @@ let _ = &mut x; // ERROR: Cannot borrow `x` as mutable.
365365
c();
366366
```
367367

368-
r[type.closure.capture.precision.discriminants.slice-patterns]
369-
Matching against a [slice pattern][patterns.slice] that needs to inspect the length of the scrutinee performs a read of the pointer value in order to fetch the length. The read will cause the closure to borrow the relevant place by `ImmBorrow`.
368+
r[type.closure.capture.precision.discriminants.slice-patterns-slices]
369+
Matching a slice against a [slice pattern][patterns.slice] other than one with only a single [rest pattern][patterns.rest] (i.e. `[..]`) reads the length from the wide pointer and captures the pointer's place by `ImmBorrow`.
370370

371-
```rust,compile_fail,E0506
372-
let x: &mut [i32] = &mut [1, 2, 3];
373-
let c = || match x { // captures `*x` by ImmBorrow
374-
[_, _, _] => println!("three elements"),
375-
_ => println!("something else"),
371+
```rust,compile_fail,E0502
372+
let mut x: &mut [u8] = &mut [];
373+
let c = || match x { // Captures `x` by `ImmBorrow`.
374+
[] => (),
375+
// ^^
376+
// This matches a slice of exactly zero elements. To know whether the
377+
// scrutinee matches, the length must be read from the wide pointer,
378+
// causing it to be captured.
379+
_ => (),
376380
};
377-
x[0] += 1; // ERROR: cannot assign to `x[_]` because it is borrowed
381+
let _ = &mut x; // ERROR: Cannot borrow `x` as mutable.
378382
c();
379383
```
380384

381-
As such, matching against an array doesn't itself cause any borrows, as the lengthh is fixed and the pattern doesn't need to inspect it.
382-
383-
```rust
384-
let mut x: [i32; 3] = [1, 2, 3];
385-
let c = || match x { // does not capture `x`
386-
[_, _, _] => println!("three elements, obviously"),
385+
```rust,no_run
386+
let x: &mut [u8] = &mut [];
387+
let c = || match x { // Does not capture `x`.
388+
[..] => (),
389+
// ^^ Rest pattern.
387390
};
388-
x[0] += 1; // `x` can be modified while the closure is live
391+
x; // OK: `x` can be moved here.
389392
c();
390393
```
391394

392-
Likewise, a slice pattern that matches slices of all possible lengths does not constitute a read.
395+
r[type.closure.capture.precision.discriminants.slice-patterns-arrays]
396+
As the length of an array is fixed by its type, matching an array against a slice pattern does not by itself capture the place.
393397

394-
```rust
395-
let x: &mut [i32] = &mut [1, 2, 3];
396-
let c = || match x { // does not capture `x`
397-
[..] => println!("always matches"),
398+
```rust,no_run
399+
let x: [u8; 1] = [0];
400+
let c = || match x { // Does not capture `x`.
401+
[_] => (), // Length is fixed.
398402
};
399-
x[0] += 1; // `x` can be modified while the closure is live
403+
x; // OK: `x` can be moved here.
400404
c();
401405
```
402406

0 commit comments

Comments
 (0)