@@ -16,6 +16,7 @@ use crate::build::expr::as_place::PlaceBuilder;
16
16
use crate :: build:: matches:: { Ascription , Binding , Candidate , MatchPair } ;
17
17
use crate :: build:: Builder ;
18
18
use rustc_middle:: thir:: { self , * } ;
19
+ use smallvec:: SmallVec ;
19
20
20
21
use std:: mem;
21
22
@@ -33,13 +34,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
33
34
///
34
35
/// only generates a single switch. If this happens this method returns
35
36
/// `true`.
36
- #[ instrument( skip( self , candidate ) , level = "debug" ) ]
37
+ #[ instrument( skip( self ) , level = "debug" ) ]
37
38
pub ( super ) fn simplify_candidate < ' pat > (
38
39
& mut self ,
39
- candidate : & mut Candidate < ' pat , ' tcx > ,
40
+ bindings : & mut Vec < Binding < ' tcx > > ,
41
+ ascriptions : & mut Vec < Ascription < ' tcx > > ,
42
+ match_pairs : & mut SmallVec < [ MatchPair < ' pat , ' tcx > ; 1 ] > ,
43
+ subcandidates : & mut Vec < Candidate < ' pat , ' tcx > > ,
44
+ has_guard : bool ,
40
45
) -> bool {
46
+ self . simplify_candidate_inner ( bindings, ascriptions, match_pairs) ;
47
+
48
+ if let [ MatchPair { pattern : Pat { kind : PatKind :: Or { pats } , .. } , place, .. } ] =
49
+ & * * match_pairs
50
+ {
51
+ * subcandidates = self . create_or_subcandidates ( place, pats, has_guard) ;
52
+ match_pairs. pop ( ) ;
53
+ return true ;
54
+ }
55
+
56
+ false
57
+ }
58
+
59
+ #[ instrument( skip( self ) , level = "debug" ) ]
60
+ pub ( super ) fn simplify_candidate_inner < ' pat > (
61
+ & mut self ,
62
+ candidate_bindings : & mut Vec < Binding < ' tcx > > ,
63
+ candidate_ascriptions : & mut Vec < Ascription < ' tcx > > ,
64
+ candidate_match_pairs : & mut SmallVec < [ MatchPair < ' pat , ' tcx > ; 1 ] > ,
65
+ ) {
41
66
// repeatedly simplify match pairs until fixed point is reached
42
- debug ! ( "{candidate:#?}" ) ;
43
67
44
68
// existing_bindings and new_bindings exists to keep the semantics in order.
45
69
// Reversing the binding order for bindings after `@` changes the binding order in places
@@ -59,28 +83,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
59
83
// binding in iter 2: [6, 7]
60
84
//
61
85
// final binding: [1, 2, 3, 6, 7, 4, 5]
62
- let mut existing_bindings = mem:: take ( & mut candidate . bindings ) ;
86
+ let mut existing_bindings = mem:: take ( candidate_bindings ) ;
63
87
let mut new_bindings = Vec :: new ( ) ;
64
88
loop {
65
- let match_pairs = mem:: take ( & mut candidate . match_pairs ) ;
89
+ let mut match_pairs = mem:: take ( candidate_match_pairs ) ;
66
90
67
- if let [ MatchPair { pattern : Pat { kind : PatKind :: Or { pats } , .. } , place } ] =
68
- & * match_pairs
91
+ if let [ MatchPair { pattern : Pat { kind : PatKind :: Or { .. } , .. } , .. } ] = & * match_pairs
69
92
{
70
93
existing_bindings. extend_from_slice ( & new_bindings) ;
71
- mem:: swap ( & mut candidate . bindings , & mut existing_bindings) ;
72
- candidate . subcandidates = self . create_or_subcandidates ( candidate , place , pats ) ;
73
- return true ;
94
+ mem:: swap ( candidate_bindings , & mut existing_bindings) ;
95
+ mem :: swap ( candidate_match_pairs , & mut match_pairs ) ;
96
+ return ;
74
97
}
75
98
76
99
let mut changed = false ;
77
100
for match_pair in match_pairs {
78
- match self . simplify_match_pair ( match_pair, candidate) {
101
+ match self . simplify_match_pair (
102
+ match_pair,
103
+ candidate_bindings,
104
+ candidate_ascriptions,
105
+ candidate_match_pairs,
106
+ ) {
79
107
Ok ( ( ) ) => {
80
108
changed = true ;
81
109
}
82
110
Err ( match_pair) => {
83
- candidate . match_pairs . push ( match_pair) ;
111
+ candidate_match_pairs . push ( match_pair) ;
84
112
}
85
113
}
86
114
}
@@ -97,21 +125,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
97
125
// let z = x.copy_field;
98
126
// let y = x;
99
127
// }
100
- candidate . bindings . extend_from_slice ( & new_bindings) ;
101
- mem:: swap ( & mut candidate . bindings , & mut new_bindings) ;
102
- candidate . bindings . clear ( ) ;
128
+ candidate_bindings . extend_from_slice ( & new_bindings) ;
129
+ mem:: swap ( candidate_bindings , & mut new_bindings) ;
130
+ candidate_bindings . clear ( ) ;
103
131
104
132
if !changed {
105
133
existing_bindings. extend_from_slice ( & new_bindings) ;
106
- mem:: swap ( & mut candidate . bindings , & mut existing_bindings) ;
134
+ mem:: swap ( candidate_bindings , & mut existing_bindings) ;
107
135
// Move or-patterns to the end, because they can result in us
108
136
// creating additional candidates, so we want to test them as
109
137
// late as possible.
110
- candidate
111
- . match_pairs
138
+ candidate_match_pairs
112
139
. sort_by_key ( |pair| matches ! ( pair. pattern. kind, PatKind :: Or { .. } ) ) ;
113
- debug ! ( simplified = ?candidate , "simplify_candidate" ) ;
114
- return false ; // if we were not able to simplify any, done.
140
+ debug ! ( simplified = ?candidate_match_pairs , "simplify_candidate" ) ;
141
+ return ; // if we were not able to simplify any, done.
115
142
}
116
143
}
117
144
}
@@ -121,14 +148,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
121
148
/// `pats`.
122
149
fn create_or_subcandidates < ' pat > (
123
150
& mut self ,
124
- candidate : & Candidate < ' pat , ' tcx > ,
125
151
place : & PlaceBuilder < ' tcx > ,
126
152
pats : & ' pat [ Box < Pat < ' tcx > > ] ,
153
+ has_guard : bool ,
127
154
) -> Vec < Candidate < ' pat , ' tcx > > {
128
155
pats. iter ( )
129
156
. map ( |box pat| {
130
- let mut candidate = Candidate :: new ( place. clone ( ) , pat, candidate. has_guard , self ) ;
131
- self . simplify_candidate ( & mut candidate) ;
157
+ let mut candidate = Candidate :: new ( place. clone ( ) , pat, has_guard, self ) ;
158
+ self . simplify_candidate (
159
+ & mut candidate. bindings ,
160
+ & mut candidate. ascriptions ,
161
+ & mut candidate. match_pairs ,
162
+ & mut candidate. subcandidates ,
163
+ candidate. has_guard ,
164
+ ) ;
132
165
candidate
133
166
} )
134
167
. collect ( )
@@ -142,7 +175,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
142
175
fn simplify_match_pair < ' pat > (
143
176
& mut self ,
144
177
match_pair : MatchPair < ' pat , ' tcx > ,
145
- candidate : & mut Candidate < ' pat , ' tcx > ,
178
+ bindings : & mut Vec < Binding < ' tcx > > ,
179
+ ascriptions : & mut Vec < Ascription < ' tcx > > ,
180
+ match_pairs : & mut SmallVec < [ MatchPair < ' pat , ' tcx > ; 1 ] > ,
146
181
) -> Result < ( ) , MatchPair < ' pat , ' tcx > > {
147
182
match match_pair. pattern . kind {
148
183
PatKind :: AscribeUserType {
@@ -151,14 +186,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
151
186
} => {
152
187
// Apply the type ascription to the value at `match_pair.place`, which is the
153
188
if let Some ( source) = match_pair. place . try_to_place ( self ) {
154
- candidate . ascriptions . push ( Ascription {
189
+ ascriptions. push ( Ascription {
155
190
annotation : annotation. clone ( ) ,
156
191
source,
157
192
variance,
158
193
} ) ;
159
194
}
160
195
161
- candidate . match_pairs . push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
196
+ match_pairs. push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
162
197
163
198
Ok ( ( ) )
164
199
}
@@ -178,7 +213,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
178
213
is_primary : _,
179
214
} => {
180
215
if let Some ( source) = match_pair. place . try_to_place ( self ) {
181
- candidate . bindings . push ( Binding {
216
+ bindings. push ( Binding {
182
217
span : match_pair. pattern . span ,
183
218
source,
184
219
var_id : var,
@@ -188,7 +223,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
188
223
189
224
if let Some ( subpattern) = subpattern. as_ref ( ) {
190
225
// this is the `x @ P` case; have to keep matching against `P` now
191
- candidate . match_pairs . push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
226
+ match_pairs. push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
192
227
}
193
228
194
229
Ok ( ( ) )
@@ -206,7 +241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
206
241
}
207
242
208
243
PatKind :: InlineConstant { subpattern : ref pattern, def : _ } => {
209
- candidate . match_pairs . push ( MatchPair :: new ( match_pair. place , pattern, self ) ) ;
244
+ match_pairs. push ( MatchPair :: new ( match_pair. place , pattern, self ) ) ;
210
245
211
246
Ok ( ( ) )
212
247
}
@@ -222,13 +257,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
222
257
PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
223
258
if prefix. is_empty ( ) && slice. is_some ( ) && suffix. is_empty ( ) {
224
259
// irrefutable
225
- self . prefix_slice_suffix (
226
- & mut candidate. match_pairs ,
227
- & match_pair. place ,
228
- prefix,
229
- slice,
230
- suffix,
231
- ) ;
260
+ self . prefix_slice_suffix ( match_pairs, & match_pair. place , prefix, slice, suffix) ;
232
261
Ok ( ( ) )
233
262
} else {
234
263
Err ( match_pair)
@@ -248,35 +277,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
248
277
|| !adt_def. is_variant_list_non_exhaustive ( ) ) ;
249
278
if irrefutable {
250
279
let place_builder = match_pair. place . downcast ( adt_def, variant_index) ;
251
- candidate
252
- . match_pairs
253
- . extend ( self . field_match_pairs ( place_builder, subpatterns) ) ;
280
+ match_pairs. extend ( self . field_match_pairs ( place_builder, subpatterns) ) ;
254
281
Ok ( ( ) )
255
282
} else {
256
283
Err ( match_pair)
257
284
}
258
285
}
259
286
260
287
PatKind :: Array { ref prefix, ref slice, ref suffix } => {
261
- self . prefix_slice_suffix (
262
- & mut candidate. match_pairs ,
263
- & match_pair. place ,
264
- prefix,
265
- slice,
266
- suffix,
267
- ) ;
288
+ self . prefix_slice_suffix ( match_pairs, & match_pair. place , prefix, slice, suffix) ;
268
289
Ok ( ( ) )
269
290
}
270
291
271
292
PatKind :: Leaf { ref subpatterns } => {
272
293
// tuple struct, match subpats (if any)
273
- candidate . match_pairs . extend ( self . field_match_pairs ( match_pair. place , subpatterns) ) ;
294
+ match_pairs. extend ( self . field_match_pairs ( match_pair. place , subpatterns) ) ;
274
295
Ok ( ( ) )
275
296
}
276
297
277
298
PatKind :: Deref { ref subpattern } => {
278
299
let place_builder = match_pair. place . deref ( ) ;
279
- candidate . match_pairs . push ( MatchPair :: new ( place_builder, subpattern, self ) ) ;
300
+ match_pairs. push ( MatchPair :: new ( place_builder, subpattern, self ) ) ;
280
301
Ok ( ( ) )
281
302
}
282
303
0 commit comments