-
Notifications
You must be signed in to change notification settings - Fork 32
/
patterns-capture-analysis.rs
208 lines (194 loc) · 5.38 KB
/
patterns-capture-analysis.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//@ 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
// of if it creates a binding
fn test_1_should_capture() {
let variant = Some(2229);
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
match variant {
//~^ NOTE: Capturing variant[] -> ImmBorrow
//~| NOTE: Min Capture variant[] -> ImmBorrow
Some(_) => {}
_ => {}
}
};
c();
}
// Should not capture the discriminant since only a wildcard is mentioned in the
// match arm
fn test_2_should_not_capture() {
let variant = Some(2229);
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
match variant {
_ => {}
}
};
c();
}
// Testing single variant patterns
enum SingleVariant {
Points(u32)
}
// Should not capture the discriminant since the single variant mentioned
// in the match arm does not trigger a binding
fn test_3_should_not_capture_single_variant() {
let variant = SingleVariant::Points(1);
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
match variant {
SingleVariant::Points(_) => {}
}
};
c();
}
// Should not capture the discriminant since the single variant mentioned
// in the match arm does not trigger a binding
fn test_6_should_capture_single_variant() {
let variant = SingleVariant::Points(1);
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
match variant {
//~^ NOTE: Capturing variant[] -> ImmBorrow
//~| NOTE: Capturing variant[(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture variant[] -> ImmBorrow
SingleVariant::Points(a) => {
println!("{:?}", a);
}
}
};
c();
}
// Should not capture the discriminant since only wildcards are mentioned in the
// match arm
fn test_4_should_not_capture_array() {
let array: [i32; 3] = [0; 3];
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
match array {
[_,_,_] => {}
}
};
c();
// We also do not need to capture an array
// behind a reference (#112607)
let array: &[i32; 3] = &[0; 3];
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
match array {
[_, _, _] => {}
}
};
c();
// We should still not insert a read if the array is inside an
// irrefutable pattern
struct Foo<T>(T);
let f = &Foo(&[10; 3]);
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
match f {
Foo([_, _, _]) => ()
}
};
c();
}
// Testing MultiVariant patterns
enum MVariant {
A,
B,
C,
}
// Should capture the discriminant since a variant of the multi variant enum is
// mentioned in the match arm; the discriminant is captured by the closure
// regardless of if it creates a binding
fn test_5_should_capture_multi_variant() {
let variant = MVariant::A;
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
match variant {
//~^ NOTE: Capturing variant[] -> ImmBorrow
//~| NOTE: Min Capture variant[] -> ImmBorrow
MVariant::A => {}
_ => {}
}
};
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();
test_3_should_not_capture_single_variant();
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();
}