Skip to content

Commit 6ed9182

Browse files
committed
Document how range and slice patterns can constitute discriminant reads
1 parent ab722ef commit 6ed9182

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

src/types/closure.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ let mut x = Example::A(42);
300300
let c = || {
301301
let Example::A(_) = x; // does not capture `x`
302302
};
303-
x = Example::A(57); // x can be modified while the closure is live
303+
x = Example::A(57); // `x` can be modified while the closure is live
304304
c();
305305
```
306306

@@ -330,6 +330,55 @@ x = Example::A(57); // ERROR: cannot assign to `x` because it is borrowed
330330
c();
331331
```
332332

333+
r[type.closure.capture.precision.discriminants.range-patterns]
334+
Matching against a [range pattern][patterns.range] constitutes a discriminant read, even if
335+
the range matches all possible values.
336+
337+
```rust,compile_fail,E0506
338+
let mut x = 7_u8;
339+
let c = || {
340+
let 0..=u8::MAX = x; // captures `x` by ImmBorrow
341+
};
342+
x += 1; // ERROR: cannot assign to `x` because it is borrowed
343+
c();
344+
```
345+
346+
r[type.closure.capture.precision.discriminants.slice-patterns]
347+
Matching against a [slice pattern][patterns.slice] constitutes a discriminant read if
348+
the slice pattern needs to inspect the length of the scrutinee.
349+
350+
```rust,compile_fail,E0506
351+
let mut x: &mut [i32] = &mut [1, 2, 3];
352+
let c = || match x { // captures `*x` by ImmBorrow
353+
[_, _, _] => println!("three elements"),
354+
_ => println!("something else"),
355+
};
356+
x[0] += 1; // ERROR: cannot assign to `x[_]` because it is borrowed
357+
c();
358+
```
359+
360+
Thus, matching against an array doesn't constitute a discriminant read, as the length is fixed.
361+
362+
```rust
363+
let mut x: [i32; 3] = [1, 2, 3];
364+
let c = || match x { // does not capture `x`
365+
[_, _, _] => println!("three elements, obviously"),
366+
};
367+
x[0] += 1; // `x` can be modified while the closure is live
368+
c();
369+
```
370+
371+
Likewise, a slice pattern that matches slices of all possible lengths does not constitute a discriminant read.
372+
373+
```rust
374+
let mut x: &mut [i32] = &mut [1, 2, 3];
375+
let c = || match x { // does not capture `x`
376+
[..] => println!("always matches"),
377+
};
378+
x[0] += 1; // `x` can be modified while the closure is live
379+
c();
380+
```
381+
333382
r[type.closure.capture.precision.move-dereference]
334383
### Capturing references in move contexts
335384

0 commit comments

Comments
 (0)