@@ -938,6 +938,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
938938 }
939939}
940940
941+ /// A pattern in a form suitable for generating code.
942+ #[ derive( Debug , Clone ) ]
943+ struct FlatPat < ' pat , ' tcx > {
944+ /// [`Span`] of the original pattern.
945+ span : Span ,
946+
947+ /// To match the pattern, all of these must be satisfied...
948+ // Invariant: all the `MatchPair`s are recursively simplified.
949+ // Invariant: or-patterns must be sorted to the end.
950+ match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
951+
952+ /// ...these bindings established...
953+ bindings : Vec < Binding < ' tcx > > ,
954+
955+ /// ...and these types asserted.
956+ ascriptions : Vec < Ascription < ' tcx > > ,
957+ }
958+
959+ impl < ' tcx , ' pat > FlatPat < ' pat , ' tcx > {
960+ fn new (
961+ place : PlaceBuilder < ' tcx > ,
962+ pattern : & ' pat Pat < ' tcx > ,
963+ cx : & mut Builder < ' _ , ' tcx > ,
964+ ) -> Self {
965+ let mut match_pairs = vec ! [ MatchPair :: new( place, pattern, cx) ] ;
966+ let mut bindings = Vec :: new ( ) ;
967+ let mut ascriptions = Vec :: new ( ) ;
968+
969+ cx. simplify_match_pairs ( & mut match_pairs, & mut bindings, & mut ascriptions) ;
970+
971+ FlatPat { span : pattern. span , match_pairs, bindings, ascriptions }
972+ }
973+ }
974+
941975#[ derive( Debug ) ]
942976struct Candidate < ' pat , ' tcx > {
943977 /// [`Span`] of the original pattern that gave rise to this candidate.
@@ -952,11 +986,11 @@ struct Candidate<'pat, 'tcx> {
952986 match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
953987
954988 /// ...these bindings established...
955- // Invariant: not mutated outside `Candidate::new()` .
989+ // Invariant: not mutated after candidate creation .
956990 bindings : Vec < Binding < ' tcx > > ,
957991
958992 /// ...and these types asserted...
959- // Invariant: not mutated outside `Candidate::new()` .
993+ // Invariant: not mutated after candidate creation .
960994 ascriptions : Vec < Ascription < ' tcx > > ,
961995
962996 /// ...and if this is non-empty, one of these subcandidates also has to match...
@@ -978,25 +1012,21 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
9781012 has_guard : bool ,
9791013 cx : & mut Builder < ' _ , ' tcx > ,
9801014 ) -> Self {
981- let mut candidate = Candidate {
982- span : pattern. span ,
1015+ Self :: from_flat_pat ( FlatPat :: new ( place, pattern, cx) , has_guard)
1016+ }
1017+
1018+ fn from_flat_pat ( flat_pat : FlatPat < ' pat , ' tcx > , has_guard : bool ) -> Self {
1019+ Candidate {
1020+ span : flat_pat. span ,
1021+ match_pairs : flat_pat. match_pairs ,
1022+ bindings : flat_pat. bindings ,
1023+ ascriptions : flat_pat. ascriptions ,
9831024 has_guard,
984- match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
985- bindings : Vec :: new ( ) ,
986- ascriptions : Vec :: new ( ) ,
9871025 subcandidates : Vec :: new ( ) ,
9881026 otherwise_block : None ,
9891027 pre_binding_block : None ,
9901028 next_candidate_pre_binding_block : None ,
991- } ;
992-
993- cx. simplify_match_pairs (
994- & mut candidate. match_pairs ,
995- & mut candidate. bindings ,
996- & mut candidate. ascriptions ,
997- ) ;
998-
999- candidate
1029+ }
10001030 }
10011031
10021032 /// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1059,7 +1089,7 @@ enum TestCase<'pat, 'tcx> {
10591089 Constant { value : mir:: Const < ' tcx > } ,
10601090 Range ( & ' pat PatRange < ' tcx > ) ,
10611091 Slice { len : usize , variable_length : bool } ,
1062- Or ,
1092+ Or { pats : Box < [ FlatPat < ' pat , ' tcx > ] > } ,
10631093}
10641094
10651095#[ derive( Debug , Clone ) ]
@@ -1217,7 +1247,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12171247 ) {
12181248 let mut split_or_candidate = false ;
12191249 for candidate in & mut * candidates {
1220- if let [ MatchPair { pattern : Pat { kind : PatKind :: Or { pats } , .. } , place , .. } ] =
1250+ if let [ MatchPair { test_case : TestCase :: Or { pats, .. } , .. } ] =
12211251 & * candidate. match_pairs
12221252 {
12231253 // Split a candidate in which the only match-pair is an or-pattern into multiple
@@ -1229,8 +1259,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12291259 // }
12301260 //
12311261 // only generates a single switch.
1232- candidate. subcandidates =
1233- self . create_or_subcandidates ( place, pats, candidate. has_guard ) ;
1262+ candidate. subcandidates = self . create_or_subcandidates ( pats, candidate. has_guard ) ;
12341263 candidate. match_pairs . pop ( ) ;
12351264 split_or_candidate = true ;
12361265 }
@@ -1449,7 +1478,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14491478 ) {
14501479 let ( first_candidate, remaining_candidates) = candidates. split_first_mut ( ) . unwrap ( ) ;
14511480 assert ! ( first_candidate. subcandidates. is_empty( ) ) ;
1452- if !matches ! ( first_candidate. match_pairs[ 0 ] . pattern . kind , PatKind :: Or { .. } ) {
1481+ if !matches ! ( first_candidate. match_pairs[ 0 ] . test_case , TestCase :: Or { .. } ) {
14531482 self . test_candidates (
14541483 span,
14551484 scrutinee_span,
@@ -1463,7 +1492,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14631492
14641493 let match_pairs = mem:: take ( & mut first_candidate. match_pairs ) ;
14651494 let ( first_match_pair, remaining_match_pairs) = match_pairs. split_first ( ) . unwrap ( ) ;
1466- let PatKind :: Or { ref pats } = & first_match_pair. pattern . kind else { unreachable ! ( ) } ;
1495+ let TestCase :: Or { ref pats } = & first_match_pair. test_case else { unreachable ! ( ) } ;
14671496
14681497 let remainder_start = self . cfg . start_new_block ( ) ;
14691498 let or_span = first_match_pair. pattern . span ;
@@ -1474,7 +1503,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
14741503 remainder_start,
14751504 pats,
14761505 or_span,
1477- & first_match_pair. place ,
14781506 fake_borrows,
14791507 ) ;
14801508
@@ -1514,23 +1542,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15141542 }
15151543
15161544 #[ instrument(
1517- skip( self , start_block, otherwise_block, or_span, place , fake_borrows, candidate, pats) ,
1545+ skip( self , start_block, otherwise_block, or_span, fake_borrows, candidate, pats) ,
15181546 level = "debug"
15191547 ) ]
15201548 fn test_or_pattern < ' pat > (
15211549 & mut self ,
15221550 candidate : & mut Candidate < ' pat , ' tcx > ,
15231551 start_block : BasicBlock ,
15241552 otherwise_block : BasicBlock ,
1525- pats : & ' pat [ Box < Pat < ' tcx > > ] ,
1553+ pats : & [ FlatPat < ' pat , ' tcx > ] ,
15261554 or_span : Span ,
1527- place : & PlaceBuilder < ' tcx > ,
15281555 fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
15291556 ) {
15301557 debug ! ( "candidate={:#?}\n pats={:#?}" , candidate, pats) ;
15311558 let mut or_candidates: Vec < _ > = pats
15321559 . iter ( )
1533- . map ( |pat| Candidate :: new ( place. clone ( ) , pat, candidate. has_guard , self ) )
1560+ . cloned ( )
1561+ . map ( |flat_pat| Candidate :: from_flat_pat ( flat_pat, candidate. has_guard ) )
15341562 . collect ( ) ;
15351563 let mut or_candidate_refs: Vec < _ > = or_candidates. iter_mut ( ) . collect ( ) ;
15361564 self . match_candidates (
0 commit comments