Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit dbdb509

Browse files
authoredMay 25, 2023
Rollup merge of #111831 - clubby789:capture-slice-pat, r=cjgillot
Always capture slice when pattern requires checking the length Fixes #111751 cc ``@zirconium-n,`` I see you were assigned to this but I've fixed some similar issues in the past and had an idea on how to investigate this.
2 parents 9d4527b + ace794c commit dbdb509

File tree

3 files changed

+209
-91
lines changed

3 files changed

+209
-91
lines changed
 

‎compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -438,12 +438,19 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
438438
// to borrow discr.
439439
needs_to_be_read = true;
440440
}
441-
PatKind::Or(_)
442-
| PatKind::Box(_)
443-
| PatKind::Slice(..)
444-
| PatKind::Ref(..)
445-
| PatKind::Wild => {
446-
// If the PatKind is Or, Box, Slice or Ref, the decision is made later
441+
PatKind::Slice(lhs, wild, rhs) => {
442+
// We don't need to test the length if the pattern is `[..]`
443+
if matches!((lhs, wild, rhs), (&[], Some(_), &[]))
444+
// Arrays have a statically known size, so
445+
// there is no need to read their length
446+
|| discr_place.place.base_ty.is_array()
447+
{
448+
} else {
449+
needs_to_be_read = true;
450+
}
451+
}
452+
PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => {
453+
// If the PatKind is Or, Box, or Ref, the decision is made later
447454
// as these patterns contains subpatterns
448455
// If the PatKind is Wild, the decision is made based on the other patterns being
449456
// examined

‎tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
// edition:2021
22

33
#![feature(rustc_attrs)]
4+
#![feature(stmt_expr_attributes)]
45

56
// Should capture the discriminant since a variant of a multivariant enum is
67
// mentioned in the match arm; the discriminant is captured by the closure regardless
78
// of if it creates a binding
89
fn test_1_should_capture() {
910
let variant = Some(2229);
1011
let c = #[rustc_capture_analysis]
11-
//~^ ERROR: attributes on expressions are experimental
12-
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
13-
1412
|| {
1513
//~^ First Pass analysis includes:
1614
//~| Min Capture analysis includes:
@@ -29,8 +27,6 @@ fn test_1_should_capture() {
2927
fn test_2_should_not_capture() {
3028
let variant = Some(2229);
3129
let c = #[rustc_capture_analysis]
32-
//~^ ERROR: attributes on expressions are experimental
33-
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
3430
|| {
3531
//~^ First Pass analysis includes:
3632
match variant {
@@ -50,8 +46,6 @@ enum SingleVariant {
5046
fn test_3_should_not_capture_single_variant() {
5147
let variant = SingleVariant::Points(1);
5248
let c = #[rustc_capture_analysis]
53-
//~^ ERROR: attributes on expressions are experimental
54-
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
5549
|| {
5650
//~^ First Pass analysis includes:
5751
match variant {
@@ -66,8 +60,6 @@ fn test_3_should_not_capture_single_variant() {
6660
fn test_6_should_capture_single_variant() {
6761
let variant = SingleVariant::Points(1);
6862
let c = #[rustc_capture_analysis]
69-
//~^ ERROR: attributes on expressions are experimental
70-
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
7163
|| {
7264
//~^ First Pass analysis includes:
7365
//~| Min Capture analysis includes:
@@ -88,8 +80,6 @@ fn test_6_should_capture_single_variant() {
8880
fn test_4_should_not_capture_array() {
8981
let array: [i32; 3] = [0; 3];
9082
let c = #[rustc_capture_analysis]
91-
//~^ ERROR: attributes on expressions are experimental
92-
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
9383
|| {
9484
//~^ First Pass analysis includes:
9585
match array {
@@ -112,8 +102,6 @@ enum MVariant {
112102
fn test_5_should_capture_multi_variant() {
113103
let variant = MVariant::A;
114104
let c = #[rustc_capture_analysis]
115-
//~^ ERROR: attributes on expressions are experimental
116-
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
117105
|| {
118106
//~^ First Pass analysis includes:
119107
//~| Min Capture analysis includes:
@@ -127,11 +115,69 @@ fn test_5_should_capture_multi_variant() {
127115
c();
128116
}
129117

118+
// Even though all patterns are wild, we need to read the discriminant
119+
// in order to test the slice length
120+
fn test_7_should_capture_slice_len() {
121+
let slice: &[i32] = &[1, 2, 3];
122+
let c = #[rustc_capture_analysis]
123+
|| {
124+
//~^ First Pass analysis includes:
125+
//~| Min Capture analysis includes:
126+
match slice {
127+
//~^ NOTE: Capturing slice[] -> ImmBorrow
128+
//~| NOTE: Min Capture slice[] -> ImmBorrow
129+
[_,_,_] => {},
130+
_ => {}
131+
}
132+
};
133+
c();
134+
let c = #[rustc_capture_analysis]
135+
|| {
136+
//~^ First Pass analysis includes:
137+
//~| Min Capture analysis includes:
138+
match slice {
139+
//~^ NOTE: Capturing slice[] -> ImmBorrow
140+
//~| NOTE: Min Capture slice[] -> ImmBorrow
141+
[] => {},
142+
_ => {}
143+
}
144+
};
145+
c();
146+
let c = #[rustc_capture_analysis]
147+
|| {
148+
//~^ First Pass analysis includes:
149+
//~| Min Capture analysis includes:
150+
match slice {
151+
//~^ NOTE: Capturing slice[] -> ImmBorrow
152+
//~| NOTE: Min Capture slice[] -> ImmBorrow
153+
[_, .. ,_] => {},
154+
_ => {}
155+
}
156+
};
157+
c();
158+
}
159+
160+
// Wild pattern that doesn't bind, so no capture
161+
fn test_8_capture_slice_wild() {
162+
let slice: &[i32] = &[1, 2, 3];
163+
let c = #[rustc_capture_analysis]
164+
|| {
165+
//~^ First Pass analysis includes:
166+
match slice {
167+
[..] => {},
168+
_ => {}
169+
}
170+
};
171+
c();
172+
}
173+
130174
fn main() {
131175
test_1_should_capture();
132176
test_2_should_not_capture();
133177
test_3_should_not_capture_single_variant();
134178
test_6_should_capture_single_variant();
135179
test_4_should_not_capture_array();
136180
test_5_should_capture_multi_variant();
181+
test_7_should_capture_slice_len();
182+
test_8_capture_slice_wild();
137183
}

‎tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr

Lines changed: 137 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,5 @@
1-
error[E0658]: attributes on expressions are experimental
2-
--> $DIR/patterns-capture-analysis.rs:10:14
3-
|
4-
LL | let c = #[rustc_capture_analysis]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6-
|
7-
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
8-
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
9-
10-
error[E0658]: attributes on expressions are experimental
11-
--> $DIR/patterns-capture-analysis.rs:31:14
12-
|
13-
LL | let c = #[rustc_capture_analysis]
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
15-
|
16-
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
17-
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
18-
19-
error[E0658]: attributes on expressions are experimental
20-
--> $DIR/patterns-capture-analysis.rs:52:14
21-
|
22-
LL | let c = #[rustc_capture_analysis]
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
24-
|
25-
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
26-
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
27-
28-
error[E0658]: attributes on expressions are experimental
29-
--> $DIR/patterns-capture-analysis.rs:68:14
30-
|
31-
LL | let c = #[rustc_capture_analysis]
32-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
33-
|
34-
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
35-
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
36-
37-
error[E0658]: attributes on expressions are experimental
38-
--> $DIR/patterns-capture-analysis.rs:90:14
39-
|
40-
LL | let c = #[rustc_capture_analysis]
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
42-
|
43-
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
44-
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
45-
46-
error[E0658]: attributes on expressions are experimental
47-
--> $DIR/patterns-capture-analysis.rs:114:14
48-
|
49-
LL | let c = #[rustc_capture_analysis]
50-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
51-
|
52-
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
53-
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
54-
551
error: First Pass analysis includes:
56-
--> $DIR/patterns-capture-analysis.rs:14:5
2+
--> $DIR/patterns-capture-analysis.rs:12:5
573
|
584
LL | / || {
595
LL | |
@@ -65,13 +11,13 @@ LL | | };
6511
| |_____^
6612
|
6713
note: Capturing variant[] -> ImmBorrow
68-
--> $DIR/patterns-capture-analysis.rs:17:15
14+
--> $DIR/patterns-capture-analysis.rs:15:15
6915
|
7016
LL | match variant {
7117
| ^^^^^^^
7218

7319
error: Min Capture analysis includes:
74-
--> $DIR/patterns-capture-analysis.rs:14:5
20+
--> $DIR/patterns-capture-analysis.rs:12:5
7521
|
7622
LL | / || {
7723
LL | |
@@ -83,13 +29,13 @@ LL | | };
8329
| |_____^
8430
|
8531
note: Min Capture variant[] -> ImmBorrow
86-
--> $DIR/patterns-capture-analysis.rs:17:15
32+
--> $DIR/patterns-capture-analysis.rs:15:15
8733
|
8834
LL | match variant {
8935
| ^^^^^^^
9036

9137
error: First Pass analysis includes:
92-
--> $DIR/patterns-capture-analysis.rs:34:5
38+
--> $DIR/patterns-capture-analysis.rs:30:5
9339
|
9440
LL | / || {
9541
LL | |
@@ -100,7 +46,7 @@ LL | | };
10046
| |_____^
10147

10248
error: First Pass analysis includes:
103-
--> $DIR/patterns-capture-analysis.rs:55:5
49+
--> $DIR/patterns-capture-analysis.rs:49:5
10450
|
10551
LL | / || {
10652
LL | |
@@ -111,7 +57,7 @@ LL | | };
11157
| |_____^
11258

11359
error: First Pass analysis includes:
114-
--> $DIR/patterns-capture-analysis.rs:71:5
60+
--> $DIR/patterns-capture-analysis.rs:63:5
11561
|
11662
LL | / || {
11763
LL | |
@@ -123,18 +69,18 @@ LL | | };
12369
| |_____^
12470
|
12571
note: Capturing variant[] -> ImmBorrow
126-
--> $DIR/patterns-capture-analysis.rs:74:15
72+
--> $DIR/patterns-capture-analysis.rs:66:15
12773
|
12874
LL | match variant {
12975
| ^^^^^^^
13076
note: Capturing variant[(0, 0)] -> ImmBorrow
131-
--> $DIR/patterns-capture-analysis.rs:74:15
77+
--> $DIR/patterns-capture-analysis.rs:66:15
13278
|
13379
LL | match variant {
13480
| ^^^^^^^
13581

13682
error: Min Capture analysis includes:
137-
--> $DIR/patterns-capture-analysis.rs:71:5
83+
--> $DIR/patterns-capture-analysis.rs:63:5
13884
|
13985
LL | / || {
14086
LL | |
@@ -146,13 +92,13 @@ LL | | };
14692
| |_____^
14793
|
14894
note: Min Capture variant[] -> ImmBorrow
149-
--> $DIR/patterns-capture-analysis.rs:74:15
95+
--> $DIR/patterns-capture-analysis.rs:66:15
15096
|
15197
LL | match variant {
15298
| ^^^^^^^
15399

154100
error: First Pass analysis includes:
155-
--> $DIR/patterns-capture-analysis.rs:93:5
101+
--> $DIR/patterns-capture-analysis.rs:83:5
156102
|
157103
LL | / || {
158104
LL | |
@@ -163,7 +109,7 @@ LL | | };
163109
| |_____^
164110

165111
error: First Pass analysis includes:
166-
--> $DIR/patterns-capture-analysis.rs:117:5
112+
--> $DIR/patterns-capture-analysis.rs:105:5
167113
|
168114
LL | / || {
169115
LL | |
@@ -175,13 +121,13 @@ LL | | };
175121
| |_____^
176122
|
177123
note: Capturing variant[] -> ImmBorrow
178-
--> $DIR/patterns-capture-analysis.rs:120:15
124+
--> $DIR/patterns-capture-analysis.rs:108:15
179125
|
180126
LL | match variant {
181127
| ^^^^^^^
182128

183129
error: Min Capture analysis includes:
184-
--> $DIR/patterns-capture-analysis.rs:117:5
130+
--> $DIR/patterns-capture-analysis.rs:105:5
185131
|
186132
LL | / || {
187133
LL | |
@@ -193,11 +139,130 @@ LL | | };
193139
| |_____^
194140
|
195141
note: Min Capture variant[] -> ImmBorrow
196-
--> $DIR/patterns-capture-analysis.rs:120:15
142+
--> $DIR/patterns-capture-analysis.rs:108:15
197143
|
198144
LL | match variant {
199145
| ^^^^^^^
200146

201-
error: aborting due to 15 previous errors
147+
error: First Pass analysis includes:
148+
--> $DIR/patterns-capture-analysis.rs:123:5
149+
|
150+
LL | / || {
151+
LL | |
152+
LL | |
153+
LL | | match slice {
154+
... |
155+
LL | | }
156+
LL | | };
157+
| |_____^
158+
|
159+
note: Capturing slice[] -> ImmBorrow
160+
--> $DIR/patterns-capture-analysis.rs:126:15
161+
|
162+
LL | match slice {
163+
| ^^^^^
164+
165+
error: Min Capture analysis includes:
166+
--> $DIR/patterns-capture-analysis.rs:123:5
167+
|
168+
LL | / || {
169+
LL | |
170+
LL | |
171+
LL | | match slice {
172+
... |
173+
LL | | }
174+
LL | | };
175+
| |_____^
176+
|
177+
note: Min Capture slice[] -> ImmBorrow
178+
--> $DIR/patterns-capture-analysis.rs:126:15
179+
|
180+
LL | match slice {
181+
| ^^^^^
182+
183+
error: First Pass analysis includes:
184+
--> $DIR/patterns-capture-analysis.rs:135:5
185+
|
186+
LL | / || {
187+
LL | |
188+
LL | |
189+
LL | | match slice {
190+
... |
191+
LL | | }
192+
LL | | };
193+
| |_____^
194+
|
195+
note: Capturing slice[] -> ImmBorrow
196+
--> $DIR/patterns-capture-analysis.rs:138:15
197+
|
198+
LL | match slice {
199+
| ^^^^^
200+
201+
error: Min Capture analysis includes:
202+
--> $DIR/patterns-capture-analysis.rs:135:5
203+
|
204+
LL | / || {
205+
LL | |
206+
LL | |
207+
LL | | match slice {
208+
... |
209+
LL | | }
210+
LL | | };
211+
| |_____^
212+
|
213+
note: Min Capture slice[] -> ImmBorrow
214+
--> $DIR/patterns-capture-analysis.rs:138:15
215+
|
216+
LL | match slice {
217+
| ^^^^^
218+
219+
error: First Pass analysis includes:
220+
--> $DIR/patterns-capture-analysis.rs:147:5
221+
|
222+
LL | / || {
223+
LL | |
224+
LL | |
225+
LL | | match slice {
226+
... |
227+
LL | | }
228+
LL | | };
229+
| |_____^
230+
|
231+
note: Capturing slice[] -> ImmBorrow
232+
--> $DIR/patterns-capture-analysis.rs:150:15
233+
|
234+
LL | match slice {
235+
| ^^^^^
236+
237+
error: Min Capture analysis includes:
238+
--> $DIR/patterns-capture-analysis.rs:147:5
239+
|
240+
LL | / || {
241+
LL | |
242+
LL | |
243+
LL | | match slice {
244+
... |
245+
LL | | }
246+
LL | | };
247+
| |_____^
248+
|
249+
note: Min Capture slice[] -> ImmBorrow
250+
--> $DIR/patterns-capture-analysis.rs:150:15
251+
|
252+
LL | match slice {
253+
| ^^^^^
254+
255+
error: First Pass analysis includes:
256+
--> $DIR/patterns-capture-analysis.rs:164:5
257+
|
258+
LL | / || {
259+
LL | |
260+
LL | | match slice {
261+
LL | | [..] => {},
262+
LL | | _ => {}
263+
LL | | }
264+
LL | | };
265+
| |_____^
266+
267+
error: aborting due to 16 previous errors
202268

203-
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)
Please sign in to comment.