@@ -22,8 +22,6 @@ use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
22
22
use rustc_span:: symbol:: Symbol ;
23
23
use rustc_span:: { BytePos , Pos , Span } ;
24
24
use rustc_target:: abi:: VariantIdx ;
25
- use smallvec:: { smallvec, SmallVec } ;
26
-
27
25
// helper functions, broken out by category:
28
26
mod simplify;
29
27
mod test;
@@ -949,12 +947,16 @@ struct Candidate<'pat, 'tcx> {
949
947
has_guard : bool ,
950
948
951
949
/// 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 > > ,
953
953
954
954
/// ...these bindings established...
955
+ // Invariant: not mutated outside `Candidate::new()`.
955
956
bindings : Vec < Binding < ' tcx > > ,
956
957
957
958
/// ...and these types asserted...
959
+ // Invariant: not mutated outside `Candidate::new()`.
958
960
ascriptions : Vec < Ascription < ' tcx > > ,
959
961
960
962
/// ...and if this is non-empty, one of these subcandidates also has to match...
@@ -974,19 +976,27 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
974
976
place : PlaceBuilder < ' tcx > ,
975
977
pattern : & ' pat Pat < ' tcx > ,
976
978
has_guard : bool ,
977
- cx : & Builder < ' _ , ' tcx > ,
979
+ cx : & mut Builder < ' _ , ' tcx > ,
978
980
) -> Self {
979
- Candidate {
981
+ let mut candidate = Candidate {
980
982
span : pattern. span ,
981
983
has_guard,
982
- match_pairs : smallvec ! [ MatchPair :: new( place, pattern, cx) ] ,
984
+ match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
983
985
bindings : Vec :: new ( ) ,
984
986
ascriptions : Vec :: new ( ) ,
985
987
subcandidates : Vec :: new ( ) ,
986
988
otherwise_block : None ,
987
989
pre_binding_block : None ,
988
990
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
990
1000
}
991
1001
992
1002
/// Visit the leaf candidates (those with no subcandidates) contained in
@@ -1042,13 +1052,18 @@ struct Ascription<'tcx> {
1042
1052
variance : ty:: Variance ,
1043
1053
}
1044
1054
1045
- #[ derive( Clone , Debug ) ]
1055
+ #[ derive( Debug ) ]
1046
1056
pub ( crate ) struct MatchPair < ' pat , ' tcx > {
1047
- // this place...
1057
+ // This place...
1048
1058
place : PlaceBuilder < ' tcx > ,
1049
1059
1050
1060
// ... 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.
1051
1063
pattern : & ' pat Pat < ' tcx > ,
1064
+
1065
+ /// Precomputed sub-match pairs of `pattern`.
1066
+ subpairs : Vec < Self > ,
1052
1067
}
1053
1068
1054
1069
/// See [`Test`] for more.
@@ -1165,12 +1180,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1165
1180
candidates : & mut [ & mut Candidate < ' pat , ' tcx > ] ,
1166
1181
fake_borrows : & mut Option < FxIndexSet < Place < ' tcx > > > ,
1167
1182
) {
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.
1171
1183
let mut split_or_candidate = false ;
1172
1184
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
+ }
1174
1202
}
1175
1203
1176
1204
ensure_sufficient_stack ( || {
0 commit comments