@@ -22,8 +22,6 @@ use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
2222use rustc_span:: symbol:: Symbol ;
2323use rustc_span:: { BytePos , Pos , Span } ;
2424use rustc_target:: abi:: VariantIdx ;
25- use smallvec:: { smallvec, SmallVec } ;
26-
2725// helper functions, broken out by category:
2826mod simplify;
2927mod test;
@@ -949,12 +947,16 @@ struct Candidate<'pat, 'tcx> {
949947 has_guard : bool ,
950948
951949 /// All of these must be satisfied...
952- match_pairs : SmallVec < [ MatchPair < ' pat , ' tcx > ; 1 ] > ,
950+ // Invariant: all the `MatchPair`s are recursively simplified.
951+ // Invariant: or-patterns must be sorted at the end.
952+ match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
953953
954954 /// ...these bindings established...
955+ // Invariant: not mutated outside `Candidate::new()`.
955956 bindings : Vec < Binding < ' tcx > > ,
956957
957958 /// ...and these types asserted...
959+ // Invariant: not mutated outside `Candidate::new()`.
958960 ascriptions : Vec < Ascription < ' tcx > > ,
959961
960962 /// ...and if this is non-empty, one of these subcandidates also has to match...
@@ -974,19 +976,27 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
974976 place : PlaceBuilder < ' tcx > ,
975977 pattern : & ' pat Pat < ' tcx > ,
976978 has_guard : bool ,
977- cx : & Builder < ' _ , ' tcx > ,
979+ cx : & mut Builder < ' _ , ' tcx > ,
978980 ) -> Self {
979- Candidate {
981+ let mut candidate = Candidate {
980982 span : pattern. span ,
981983 has_guard,
982- match_pairs : smallvec ! [ MatchPair :: new( place, pattern, cx) ] ,
984+ match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
983985 bindings : Vec :: new ( ) ,
984986 ascriptions : Vec :: new ( ) ,
985987 subcandidates : Vec :: new ( ) ,
986988 otherwise_block : None ,
987989 pre_binding_block : None ,
988990 next_candidate_pre_binding_block : None ,
989- }
991+ } ;
992+
993+ cx. simplify_match_pairs (
994+ & mut candidate. match_pairs ,
995+ & mut candidate. bindings ,
996+ & mut candidate. ascriptions ,
997+ ) ;
998+
999+ candidate
9901000 }
9911001
9921002 /// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1042,13 +1052,18 @@ struct Ascription<'tcx> {
10421052 variance : ty:: Variance ,
10431053}
10441054
1045- #[ derive( Clone , Debug ) ]
1055+ #[ derive( Debug ) ]
10461056pub ( crate ) struct MatchPair < ' pat , ' tcx > {
1047- // this place...
1057+ // This place...
10481058 place : PlaceBuilder < ' tcx > ,
10491059
10501060 // ... must match this pattern.
1061+ // Invariant: after creation and simplification in `Candidate::new()`, all match pairs must be
1062+ // simplified, i.e. require a test.
10511063 pattern : & ' pat Pat < ' tcx > ,
1064+
1065+ /// Precomputed sub-match pairs of `pattern`.
1066+ subpairs : Vec < Self > ,
10521067}
10531068
10541069/// See [`Test`] for more.
@@ -1165,12 +1180,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11651180 candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
11661181 fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
11671182 ) {
1168- // Start by simplifying candidates. Once this process is complete, all
1169- // the match pairs which remain require some form of test, whether it
1170- // be a switch or pattern comparison.
11711183 let mut split_or_candidate = false ;
11721184 for candidate in & mut * candidates {
1173- split_or_candidate |= self . simplify_candidate ( candidate) ;
1185+ if let [ MatchPair { pattern : Pat { kind : PatKind :: Or { pats } , .. } , place, .. } ] =
1186+ & * candidate. match_pairs
1187+ {
1188+ // Split a candidate in which the only match-pair is an or-pattern into multiple
1189+ // candidates. This is so that
1190+ //
1191+ // match x {
1192+ // 0 | 1 => { ... },
1193+ // 2 | 3 => { ... },
1194+ // }
1195+ //
1196+ // only generates a single switch.
1197+ candidate. subcandidates =
1198+ self . create_or_subcandidates ( place, pats, candidate. has_guard ) ;
1199+ candidate. match_pairs . pop ( ) ;
1200+ split_or_candidate = true ;
1201+ }
11741202 }
11751203
11761204 ensure_sufficient_stack ( || {
0 commit comments