@@ -300,7 +300,7 @@ let mut x = Example::A(42);
300
300
let c = || {
301
301
let Example :: A (_ ) = x ; // does not capture `x`
302
302
};
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
304
304
c ();
305
305
```
306
306
@@ -330,6 +330,55 @@ x = Example::A(57); // ERROR: cannot assign to `x` because it is borrowed
330
330
c();
331
331
```
332
332
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
+
333
382
r[ type.closure.capture.precision.move-dereference]
334
383
### Capturing references in move contexts
335
384
0 commit comments