From ace794c6d78ca2d1a8740b07f5e7f81fc09b4a02 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 21 May 2023 23:06:06 +0000 Subject: [PATCH] Always capture slice when pattern requires checking the length --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 19 +- .../match/patterns-capture-analysis.rs | 72 ++++-- .../match/patterns-capture-analysis.stderr | 209 ++++++++++++------ 3 files changed, 209 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 94b6a0f8f47d7..e14e8ac2ce000 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -438,12 +438,19 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // to borrow discr. needs_to_be_read = true; } - PatKind::Or(_) - | PatKind::Box(_) - | PatKind::Slice(..) - | PatKind::Ref(..) - | PatKind::Wild => { - // If the PatKind is Or, Box, Slice or Ref, the decision is made later + PatKind::Slice(lhs, wild, rhs) => { + // We don't need to test the length if the pattern is `[..]` + if matches!((lhs, wild, rhs), (&[], Some(_), &[])) + // Arrays have a statically known size, so + // there is no need to read their length + || discr_place.place.base_ty.is_array() + { + } else { + needs_to_be_read = true; + } + } + PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => { + // If the PatKind is Or, Box, or Ref, the decision is made later // as these patterns contains subpatterns // If the PatKind is Wild, the decision is made based on the other patterns being // examined diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs index 56f5ac44db068..41b09ba03702b 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -1,6 +1,7 @@ // edition:2021 #![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] // Should capture the discriminant since a variant of a multivariant enum is // mentioned in the match arm; the discriminant is captured by the closure regardless @@ -8,9 +9,6 @@ fn test_1_should_capture() { let variant = Some(2229); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - || { //~^ First Pass analysis includes: //~| Min Capture analysis includes: @@ -29,8 +27,6 @@ fn test_1_should_capture() { fn test_2_should_not_capture() { let variant = Some(2229); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 || { //~^ First Pass analysis includes: match variant { @@ -50,8 +46,6 @@ enum SingleVariant { fn test_3_should_not_capture_single_variant() { let variant = SingleVariant::Points(1); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 || { //~^ First Pass analysis includes: match variant { @@ -66,8 +60,6 @@ fn test_3_should_not_capture_single_variant() { fn test_6_should_capture_single_variant() { let variant = SingleVariant::Points(1); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 || { //~^ First Pass analysis includes: //~| Min Capture analysis includes: @@ -88,8 +80,6 @@ fn test_6_should_capture_single_variant() { fn test_4_should_not_capture_array() { let array: [i32; 3] = [0; 3]; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 || { //~^ First Pass analysis includes: match array { @@ -112,8 +102,6 @@ enum MVariant { fn test_5_should_capture_multi_variant() { let variant = MVariant::A; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 || { //~^ First Pass analysis includes: //~| Min Capture analysis includes: @@ -127,6 +115,62 @@ fn test_5_should_capture_multi_variant() { c(); } +// Even though all patterns are wild, we need to read the discriminant +// in order to test the slice length +fn test_7_should_capture_slice_len() { + let slice: &[i32] = &[1, 2, 3]; + let c = #[rustc_capture_analysis] + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + match slice { + //~^ NOTE: Capturing slice[] -> ImmBorrow + //~| NOTE: Min Capture slice[] -> ImmBorrow + [_,_,_] => {}, + _ => {} + } + }; + c(); + let c = #[rustc_capture_analysis] + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + match slice { + //~^ NOTE: Capturing slice[] -> ImmBorrow + //~| NOTE: Min Capture slice[] -> ImmBorrow + [] => {}, + _ => {} + } + }; + c(); + let c = #[rustc_capture_analysis] + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + match slice { + //~^ NOTE: Capturing slice[] -> ImmBorrow + //~| NOTE: Min Capture slice[] -> ImmBorrow + [_, .. ,_] => {}, + _ => {} + } + }; + c(); +} + +// Wild pattern that doesn't bind, so no capture +fn test_8_capture_slice_wild() { + let slice: &[i32] = &[1, 2, 3]; + let c = #[rustc_capture_analysis] + || { + //~^ First Pass analysis includes: + match slice { + [..] => {}, + _ => {} + } + }; + c(); +} + fn main() { test_1_should_capture(); test_2_should_not_capture(); @@ -134,4 +178,6 @@ fn main() { test_6_should_capture_single_variant(); test_4_should_not_capture_array(); test_5_should_capture_multi_variant(); + test_7_should_capture_slice_len(); + test_8_capture_slice_wild(); } diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr index 460813333952b..e137af1a0bd40 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -1,59 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:10:14 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:31:14 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:52:14 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:68:14 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:90:14 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - -error[E0658]: attributes on expressions are experimental - --> $DIR/patterns-capture-analysis.rs:114:14 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable - error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:14:5 + --> $DIR/patterns-capture-analysis.rs:12:5 | LL | / || { LL | | @@ -65,13 +11,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:17:15 + --> $DIR/patterns-capture-analysis.rs:15:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:14:5 + --> $DIR/patterns-capture-analysis.rs:12:5 | LL | / || { LL | | @@ -83,13 +29,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:17:15 + --> $DIR/patterns-capture-analysis.rs:15:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:34:5 + --> $DIR/patterns-capture-analysis.rs:30:5 | LL | / || { LL | | @@ -100,7 +46,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:55:5 + --> $DIR/patterns-capture-analysis.rs:49:5 | LL | / || { LL | | @@ -111,7 +57,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:71:5 + --> $DIR/patterns-capture-analysis.rs:63:5 | LL | / || { LL | | @@ -123,18 +69,18 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:74:15 + --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { | ^^^^^^^ note: Capturing variant[(0, 0)] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:74:15 + --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:71:5 + --> $DIR/patterns-capture-analysis.rs:63:5 | LL | / || { LL | | @@ -146,13 +92,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:74:15 + --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:93:5 + --> $DIR/patterns-capture-analysis.rs:83:5 | LL | / || { LL | | @@ -163,7 +109,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:117:5 + --> $DIR/patterns-capture-analysis.rs:105:5 | LL | / || { LL | | @@ -175,13 +121,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:120:15 + --> $DIR/patterns-capture-analysis.rs:108:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:117:5 + --> $DIR/patterns-capture-analysis.rs:105:5 | LL | / || { LL | | @@ -193,11 +139,130 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> ImmBorrow - --> $DIR/patterns-capture-analysis.rs:120:15 + --> $DIR/patterns-capture-analysis.rs:108:15 | LL | match variant { | ^^^^^^^ -error: aborting due to 15 previous errors +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:123:5 + | +LL | / || { +LL | | +LL | | +LL | | match slice { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Capturing slice[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:126:15 + | +LL | match slice { + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/patterns-capture-analysis.rs:123:5 + | +LL | / || { +LL | | +LL | | +LL | | match slice { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Min Capture slice[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:126:15 + | +LL | match slice { + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:135:5 + | +LL | / || { +LL | | +LL | | +LL | | match slice { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Capturing slice[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:138:15 + | +LL | match slice { + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/patterns-capture-analysis.rs:135:5 + | +LL | / || { +LL | | +LL | | +LL | | match slice { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Min Capture slice[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:138:15 + | +LL | match slice { + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:147:5 + | +LL | / || { +LL | | +LL | | +LL | | match slice { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Capturing slice[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:150:15 + | +LL | match slice { + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/patterns-capture-analysis.rs:147:5 + | +LL | / || { +LL | | +LL | | +LL | | match slice { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Min Capture slice[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:150:15 + | +LL | match slice { + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:164:5 + | +LL | / || { +LL | | +LL | | match slice { +LL | | [..] => {}, +LL | | _ => {} +LL | | } +LL | | }; + | |_____^ + +error: aborting due to 16 previous errors -For more information about this error, try `rustc --explain E0658`.