@@ -300,7 +300,7 @@ let mut x = Example::A(42);
300300let 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
304304c ();
305305```
306306
@@ -330,6 +330,55 @@ x = Example::A(57); // ERROR: cannot assign to `x` because it is borrowed
330330c();
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+
333382r[ type.closure.capture.precision.move-dereference]
334383### Capturing references in move contexts
335384
0 commit comments