@@ -16,6 +16,7 @@ use crate::build::expr::as_place::PlaceBuilder;
1616use crate :: build:: matches:: { Ascription , Binding , Candidate , MatchPair } ;
1717use crate :: build:: Builder ;
1818use rustc_middle:: thir:: { self , * } ;
19+ use smallvec:: SmallVec ;
1920
2021use std:: mem;
2122
@@ -33,13 +34,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3334 ///
3435 /// only generates a single switch. If this happens this method returns
3536 /// `true`.
36- #[ instrument( skip( self , candidate ) , level = "debug" ) ]
37+ #[ instrument( skip( self ) , level = "debug" ) ]
3738 pub ( super ) fn simplify_candidate < ' pat > (
3839 & 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 ,
4045 ) -> 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+ ) {
4166 // repeatedly simplify match pairs until fixed point is reached
42- debug ! ( "{candidate:#?}" ) ;
4367
4468 // existing_bindings and new_bindings exists to keep the semantics in order.
4569 // Reversing the binding order for bindings after `@` changes the binding order in places
@@ -59,28 +83,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5983 // binding in iter 2: [6, 7]
6084 //
6185 // 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 ) ;
6387 let mut new_bindings = Vec :: new ( ) ;
6488 loop {
65- let match_pairs = mem:: take ( & mut candidate . match_pairs ) ;
89+ let mut match_pairs = mem:: take ( candidate_match_pairs ) ;
6690
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
6992 {
7093 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 ;
7497 }
7598
7699 let mut changed = false ;
77100 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+ ) {
79107 Ok ( ( ) ) => {
80108 changed = true ;
81109 }
82110 Err ( match_pair) => {
83- candidate . match_pairs . push ( match_pair) ;
111+ candidate_match_pairs . push ( match_pair) ;
84112 }
85113 }
86114 }
@@ -97,21 +125,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
97125 // let z = x.copy_field;
98126 // let y = x;
99127 // }
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 ( ) ;
103131
104132 if !changed {
105133 existing_bindings. extend_from_slice ( & new_bindings) ;
106- mem:: swap ( & mut candidate . bindings , & mut existing_bindings) ;
134+ mem:: swap ( candidate_bindings , & mut existing_bindings) ;
107135 // Move or-patterns to the end, because they can result in us
108136 // creating additional candidates, so we want to test them as
109137 // late as possible.
110- candidate
111- . match_pairs
138+ candidate_match_pairs
112139 . 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.
115142 }
116143 }
117144 }
@@ -121,14 +148,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
121148 /// `pats`.
122149 fn create_or_subcandidates < ' pat > (
123150 & mut self ,
124- candidate : & Candidate < ' pat , ' tcx > ,
125151 place : & PlaceBuilder < ' tcx > ,
126152 pats : & ' pat [ Box < Pat < ' tcx > > ] ,
153+ has_guard : bool ,
127154 ) -> Vec < Candidate < ' pat , ' tcx > > {
128155 pats. iter ( )
129156 . 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+ ) ;
132165 candidate
133166 } )
134167 . collect ( )
@@ -142,7 +175,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
142175 fn simplify_match_pair < ' pat > (
143176 & mut self ,
144177 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 ] > ,
146181 ) -> Result < ( ) , MatchPair < ' pat , ' tcx > > {
147182 match match_pair. pattern . kind {
148183 PatKind :: AscribeUserType {
@@ -151,14 +186,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
151186 } => {
152187 // Apply the type ascription to the value at `match_pair.place`, which is the
153188 if let Some ( source) = match_pair. place . try_to_place ( self ) {
154- candidate . ascriptions . push ( Ascription {
189+ ascriptions. push ( Ascription {
155190 annotation : annotation. clone ( ) ,
156191 source,
157192 variance,
158193 } ) ;
159194 }
160195
161- candidate . match_pairs . push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
196+ match_pairs. push ( MatchPair :: new ( match_pair. place , subpattern, self ) ) ;
162197
163198 Ok ( ( ) )
164199 }
@@ -178,7 +213,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
178213 is_primary : _,
179214 } => {
180215 if let Some ( source) = match_pair. place . try_to_place ( self ) {
181- candidate . bindings . push ( Binding {
216+ bindings. push ( Binding {
182217 span : match_pair. pattern . span ,
183218 source,
184219 var_id : var,
@@ -188,7 +223,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
188223
189224 if let Some ( subpattern) = subpattern. as_ref ( ) {
190225 // 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 ) ) ;
192227 }
193228
194229 Ok ( ( ) )
@@ -206,7 +241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
206241 }
207242
208243 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 ) ) ;
210245
211246 Ok ( ( ) )
212247 }
@@ -222,13 +257,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
222257 PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
223258 if prefix. is_empty ( ) && slice. is_some ( ) && suffix. is_empty ( ) {
224259 // 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) ;
232261 Ok ( ( ) )
233262 } else {
234263 Err ( match_pair)
@@ -248,35 +277,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
248277 || !adt_def. is_variant_list_non_exhaustive ( ) ) ;
249278 if irrefutable {
250279 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) ) ;
254281 Ok ( ( ) )
255282 } else {
256283 Err ( match_pair)
257284 }
258285 }
259286
260287 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) ;
268289 Ok ( ( ) )
269290 }
270291
271292 PatKind :: Leaf { ref subpatterns } => {
272293 // 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) ) ;
274295 Ok ( ( ) )
275296 }
276297
277298 PatKind :: Deref { ref subpattern } => {
278299 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 ) ) ;
280301 Ok ( ( ) )
281302 }
282303
0 commit comments