6
6
//! - `place @ (P1, P2)` can be simplified to `[place.0 @ P1, place.1 @ P2]`
7
7
//! - `place @ x` can be simplified to `[]` by binding `x` to `place`
8
8
//!
9
- //! The `simplify_candidate ` routine just repeatedly applies these
9
+ //! The `simplify_match_pairs ` routine just repeatedly applies these
10
10
//! sort of simplifications until there is nothing left to
11
11
//! simplify. Match pairs cannot be simplified if they require some
12
12
//! sort of test: for example, testing which variant an enum is, or
@@ -22,10 +22,15 @@ use rustc_middle::ty;
22
22
use std:: mem;
23
23
24
24
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
25
- /// Simplify a candidate so that all match pairs require a test.
26
- #[ instrument( skip( self , candidate) , level = "debug" ) ]
27
- pub ( super ) fn simplify_candidate < ' pat > ( & mut self , candidate : & mut Candidate < ' pat , ' tcx > ) {
28
- debug ! ( "{candidate:#?}" ) ;
25
+ /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
26
+ /// ascriptions in the provided `Vec`s.
27
+ #[ instrument( skip( self ) , level = "debug" ) ]
28
+ pub ( super ) fn simplify_match_pairs < ' pat > (
29
+ & mut self ,
30
+ match_pairs : & mut Vec < MatchPair < ' pat , ' tcx > > ,
31
+ candidate_bindings : & mut Vec < Binding < ' tcx > > ,
32
+ candidate_ascriptions : & mut Vec < Ascription < ' tcx > > ,
33
+ ) {
29
34
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
30
35
// bindings in `pat` before `x`. E.g. (#69971):
31
36
//
@@ -53,60 +58,70 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
53
58
// bindings in iter 2: [6, 7]
54
59
//
55
60
// final bindings: [6, 7, 4, 5, 1, 2, 3]
56
- let mut accumulated_bindings = mem:: take ( & mut candidate . bindings ) ;
61
+ let mut accumulated_bindings = mem:: take ( candidate_bindings ) ;
57
62
// Repeatedly simplify match pairs until fixed point is reached
58
63
loop {
59
64
let mut changed = false ;
60
- for match_pair in mem:: take ( & mut candidate. match_pairs ) {
61
- match self . simplify_match_pair ( match_pair, candidate) {
65
+ for match_pair in mem:: take ( match_pairs) {
66
+ match self . simplify_match_pair (
67
+ match_pair,
68
+ candidate_bindings,
69
+ candidate_ascriptions,
70
+ match_pairs,
71
+ ) {
62
72
Ok ( ( ) ) => {
63
73
changed = true ;
64
74
}
65
75
Err ( match_pair) => {
66
- candidate . match_pairs . push ( match_pair) ;
76
+ match_pairs. push ( match_pair) ;
67
77
}
68
78
}
69
79
}
70
80
71
81
// This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings
72
- candidate . bindings . extend_from_slice ( & accumulated_bindings) ;
73
- mem:: swap ( & mut candidate . bindings , & mut accumulated_bindings) ;
74
- candidate . bindings . clear ( ) ;
82
+ candidate_bindings . extend_from_slice ( & accumulated_bindings) ;
83
+ mem:: swap ( candidate_bindings , & mut accumulated_bindings) ;
84
+ candidate_bindings . clear ( ) ;
75
85
76
86
if !changed {
77
87
// If we were not able to simplify anymore, done.
78
88
break ;
79
89
}
80
90
}
81
91
82
- // Store computed bindings back in `candidate `.
83
- mem:: swap ( & mut candidate . bindings , & mut accumulated_bindings) ;
92
+ // Store computed bindings back in `candidate_bindings `.
93
+ mem:: swap ( candidate_bindings , & mut accumulated_bindings) ;
84
94
85
95
// Move or-patterns to the end, because they can result in us
86
96
// creating additional candidates, so we want to test them as
87
97
// late as possible.
88
- candidate . match_pairs . sort_by_key ( |pair| matches ! ( pair. pattern. kind, PatKind :: Or { .. } ) ) ;
89
- debug ! ( simplified = ?candidate , "simplify_candidate " ) ;
98
+ match_pairs. sort_by_key ( |pair| matches ! ( pair. pattern. kind, PatKind :: Or { .. } ) ) ;
99
+ debug ! ( simplified = ?match_pairs , "simplify_match_pairs " ) ;
90
100
}
91
101
92
102
/// Given `candidate` that has a single or-pattern for its match-pairs,
93
103
/// creates a fresh candidate for each of its input subpatterns passed via
94
104
/// `pats`.
95
105
pub ( super ) fn create_or_subcandidates < ' pat > (
96
106
& mut self ,
97
- candidate : & Candidate < ' pat , ' tcx > ,
98
107
place : & PlaceBuilder < ' tcx > ,
99
108
pats : & ' pat [ Box < Pat < ' tcx > > ] ,
109
+ has_guard : bool ,
100
110
) -> Vec < Candidate < ' pat , ' tcx > > {
101
111
pats. iter ( )
102
112
. map ( |box pat| {
103
- let mut candidate = Candidate :: new ( place. clone ( ) , pat, candidate. has_guard , self ) ;
104
- self . simplify_candidate ( & mut candidate) ;
113
+ let mut candidate = Candidate :: new ( place. clone ( ) , pat, has_guard, self ) ;
114
+ self . simplify_match_pairs (
115
+ & mut candidate. match_pairs ,
116
+ & mut candidate. bindings ,
117
+ & mut candidate. ascriptions ,
118
+ ) ;
105
119
106
120
if let [ MatchPair { pattern : Pat { kind : PatKind :: Or { pats } , .. } , place, .. } ] =
107
121
& * candidate. match_pairs
108
122
{
109
- candidate. subcandidates = self . create_or_subcandidates ( & candidate, place, pats) ;
123
+ candidate. subcandidates =
124
+ self . create_or_subcandidates ( place, pats, candidate. has_guard ) ;
110
125
candidate. match_pairs . pop ( ) ;
111
126
}
112
127
candidate
@@ -122,7 +137,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
122
137
fn simplify_match_pair < ' pat > (
123
138
& mut self ,
124
139
match_pair : MatchPair < ' pat , ' tcx > ,
125
- candidate : & mut Candidate < ' pat , ' tcx > ,
140
+ bindings : & mut Vec < Binding < ' tcx > > ,
141
+ ascriptions : & mut Vec < Ascription < ' tcx > > ,
142
+ match_pairs : & mut Vec < MatchPair < ' pat , ' tcx > > ,
126
143
) -> Result < ( ) , MatchPair < ' pat , ' tcx > > {
127
144
match match_pair. pattern . kind {
128
145
PatKind :: AscribeUserType {
@@ -131,14 +148,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
131
148
} => {
132
149
// Apply the type ascription to the value at `match_pair.place`
133
150
if let Some ( source) = match_pair. place . try_to_place ( self ) {
134
- candidate . ascriptions . push ( Ascription {
151
+ ascriptions. push ( Ascription {
135
152
annotation : annotation. clone ( ) ,
136
153
source,
137
154
variance,
138
155
} ) ;
139
156
}
140
157
141
- candidate . match_pairs . push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
158
+ match_pairs. push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
142
159
143
160
Ok ( ( ) )
144
161
}
@@ -158,7 +175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
158
175
is_primary : _,
159
176
} => {
160
177
if let Some ( source) = match_pair. place . try_to_place ( self ) {
161
- candidate . bindings . push ( Binding {
178
+ bindings. push ( Binding {
162
179
span : match_pair. pattern . span ,
163
180
source,
164
181
var_id : var,
@@ -168,7 +185,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
168
185
169
186
if let Some ( subpattern) = subpattern. as_ref ( ) {
170
187
// this is the `x @ P` case; have to keep matching against `P` now
171
- candidate . match_pairs . push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
188
+ match_pairs. push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
172
189
}
173
190
174
191
Ok ( ( ) )
@@ -211,13 +228,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
211
228
span,
212
229
user_ty : Box :: new ( user_ty) ,
213
230
} ;
214
- candidate . ascriptions . push ( Ascription {
231
+ ascriptions. push ( Ascription {
215
232
annotation,
216
233
source,
217
234
variance : ty:: Contravariant ,
218
235
} ) ;
219
236
}
220
- candidate . match_pairs . push ( MatchPair :: new ( match_pair. place , pattern, self ) ) ;
237
+ match_pairs. push ( MatchPair :: new ( match_pair. place , pattern, self ) ) ;
221
238
222
239
Ok ( ( ) )
223
240
}
@@ -233,13 +250,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
233
250
PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
234
251
if prefix. is_empty ( ) && slice. is_some ( ) && suffix. is_empty ( ) {
235
252
// irrefutable
236
- self . prefix_slice_suffix (
237
- & mut candidate. match_pairs ,
238
- & match_pair. place ,
239
- prefix,
240
- slice,
241
- suffix,
242
- ) ;
253
+ self . prefix_slice_suffix ( match_pairs, & match_pair. place , prefix, slice, suffix) ;
243
254
Ok ( ( ) )
244
255
} else {
245
256
Err ( match_pair)
@@ -260,35 +271,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
260
271
|| !adt_def. is_variant_list_non_exhaustive ( ) ) ;
261
272
if irrefutable {
262
273
let place_builder = match_pair. place . downcast ( adt_def, variant_index) ;
263
- candidate
264
- . match_pairs
265
- . extend ( self . field_match_pairs ( place_builder, subpatterns) ) ;
274
+ match_pairs. extend ( self . field_match_pairs ( place_builder, subpatterns) ) ;
266
275
Ok ( ( ) )
267
276
} else {
268
277
Err ( match_pair)
269
278
}
270
279
}
271
280
272
281
PatKind :: Array { ref prefix, ref slice, ref suffix } => {
273
- self . prefix_slice_suffix (
274
- & mut candidate. match_pairs ,
275
- & match_pair. place ,
276
- prefix,
277
- slice,
278
- suffix,
279
- ) ;
282
+ self . prefix_slice_suffix ( match_pairs, & match_pair. place , prefix, slice, suffix) ;
280
283
Ok ( ( ) )
281
284
}
282
285
283
286
PatKind :: Leaf { ref subpatterns } => {
284
287
// tuple struct, match subpats (if any)
285
- candidate . match_pairs . extend ( self . field_match_pairs ( match_pair. place , subpatterns) ) ;
288
+ match_pairs. extend ( self . field_match_pairs ( match_pair. place , subpatterns) ) ;
286
289
Ok ( ( ) )
287
290
}
288
291
289
292
PatKind :: Deref { ref subpattern } => {
290
293
let place_builder = match_pair. place . deref ( ) ;
291
- candidate . match_pairs . push ( MatchPair :: new ( place_builder, subpattern, self ) ) ;
294
+ match_pairs. push ( MatchPair :: new ( place_builder, subpattern, self ) ) ;
292
295
Ok ( ( ) )
293
296
}
294
297
0 commit comments