@@ -1240,9 +1240,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12401240 ) {
12411241 let mut split_or_candidate = false ;
12421242 for candidate in & mut * candidates {
1243- if let [ MatchPair { test_case : TestCase :: Or { pats, .. } , .. } ] =
1244- & * candidate. match_pairs
1245- {
1243+ if let [ MatchPair { test_case : TestCase :: Or { .. } , .. } ] = & * candidate. match_pairs {
12461244 // Split a candidate in which the only match-pair is an or-pattern into multiple
12471245 // candidates. This is so that
12481246 //
@@ -1252,9 +1250,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12521250 // }
12531251 //
12541252 // only generates a single switch.
1255- candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
1256- let first_match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1257- candidate. or_span = Some ( first_match_pair. pattern . span ) ;
1253+ let match_pair = candidate. match_pairs . pop ( ) . unwrap ( ) ;
1254+ self . create_or_subcandidates ( candidate, & match_pair) ;
12581255 split_or_candidate = true ;
12591256 }
12601257 }
@@ -1444,12 +1441,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14441441
14451442 let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
14461443 let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1447- let TestCase :: Or { ref pats } = & first_match_pair. test_case else { unreachable ! ( ) } ;
14481444
14491445 let remainder_start = self . cfg . start_new_block ( ) ;
1450- let or_span = first_match_pair. pattern . span ;
14511446 // Test the alternatives of this or-pattern.
1452- self . test_or_pattern ( first_candidate, start_block, remainder_start, pats , or_span ) ;
1447+ self . test_or_pattern ( first_candidate, start_block, remainder_start, first_match_pair ) ;
14531448
14541449 if !remaining_match_pairs. is_empty ( ) {
14551450 // If more match pairs remain, test them after each subcandidate.
@@ -1484,39 +1479,48 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14841479 ) ;
14851480 }
14861481
1487- #[ instrument(
1488- skip( self , start_block, otherwise_block, or_span, candidate, pats) ,
1489- level = "debug"
1490- ) ]
1482+ #[ instrument( skip( self , start_block, otherwise_block, candidate, match_pair) , level = "debug" ) ]
14911483 fn test_or_pattern < ' pat > (
14921484 & mut self ,
14931485 candidate : & mut Candidate < ' pat , ' tcx > ,
14941486 start_block : BasicBlock ,
14951487 otherwise_block : BasicBlock ,
1496- pats : & [ FlatPat < ' pat , ' tcx > ] ,
1497- or_span : Span ,
1488+ match_pair : & MatchPair < ' pat , ' tcx > ,
14981489 ) {
1499- debug ! ( "candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1500- let mut or_candidates: Vec < _ > = pats
1501- . iter ( )
1502- . cloned ( )
1503- . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1504- . collect ( ) ;
1505- let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
1490+ self . create_or_subcandidates ( candidate, match_pair) ;
1491+ let mut or_candidate_refs: Vec < _ > = candidate. subcandidates . iter_mut ( ) . collect ( ) ;
1492+ let or_span = match_pair. pattern . span ;
15061493 self . match_candidates (
15071494 or_span,
15081495 or_span,
15091496 start_block,
15101497 otherwise_block,
15111498 & mut or_candidate_refs,
15121499 ) ;
1513- candidate. subcandidates = or_candidates;
1514- candidate. or_span = Some ( or_span) ;
15151500 self . merge_trivial_subcandidates ( candidate) ;
15161501 }
15171502
1518- /// Try to merge all of the subcandidates of the given candidate into one.
1519- /// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`.
1503+ /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
1504+ /// subcandidate. Any candidate that has been expanded that way should be passed to
1505+ /// `merge_trivial_subcandidates` after its subcandidates have been processed.
1506+ fn create_or_subcandidates < ' pat > (
1507+ & mut self ,
1508+ candidate : & mut Candidate < ' pat , ' tcx > ,
1509+ match_pair : & MatchPair < ' pat , ' tcx > ,
1510+ ) {
1511+ let TestCase :: Or { ref pats } = & match_pair. test_case else { bug ! ( ) } ;
1512+ debug ! ( "expanding or-pattern: candidate={:#?}\n pats={:#?}" , candidate, pats) ;
1513+ candidate. or_span = Some ( match_pair. pattern . span ) ;
1514+ candidate. subcandidates = pats
1515+ . iter ( )
1516+ . cloned ( )
1517+ . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
1518+ . collect ( ) ;
1519+ }
1520+
1521+ /// Try to merge all of the subcandidates of the given candidate into one. This avoids
1522+ /// exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. The or-pattern should have
1523+ /// been expanded with `create_or_subcandidates`.
15201524 fn merge_trivial_subcandidates ( & mut self , candidate : & mut Candidate < ' _ , ' tcx > ) {
15211525 if candidate. subcandidates . is_empty ( ) || candidate. has_guard {
15221526 // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
0 commit comments