@@ -947,6 +947,9 @@ struct PatternExtraData<'tcx> {
947
947
948
948
/// Types that must be asserted.
949
949
ascriptions : Vec < Ascription < ' tcx > > ,
950
+
951
+ /// Whether this corresponds to a never pattern.
952
+ is_never : bool ,
950
953
}
951
954
952
955
impl < ' tcx > PatternExtraData < ' tcx > {
@@ -972,12 +975,14 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
972
975
pattern : & ' pat Pat < ' tcx > ,
973
976
cx : & mut Builder < ' _ , ' tcx > ,
974
977
) -> Self {
978
+ let is_never = pattern. is_never_pattern ( ) ;
975
979
let mut flat_pat = FlatPat {
976
980
match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
977
981
extra_data : PatternExtraData {
978
982
span : pattern. span ,
979
983
bindings : Vec :: new ( ) ,
980
984
ascriptions : Vec :: new ( ) ,
985
+ is_never,
981
986
} ,
982
987
} ;
983
988
cx. simplify_match_pairs ( & mut flat_pat. match_pairs , & mut flat_pat. extra_data ) ;
@@ -993,6 +998,8 @@ struct Candidate<'pat, 'tcx> {
993
998
match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
994
999
995
1000
/// ...and if this is non-empty, one of these subcandidates also has to match...
1001
+ // Invariant: at the end of the algorithm, this must never contain a `is_never` candidate
1002
+ // because that would break binding consistency.
996
1003
subcandidates : Vec < Candidate < ' pat , ' tcx > > ,
997
1004
998
1005
/// ...and the guard must be evaluated if there is one.
@@ -1097,6 +1104,7 @@ enum TestCase<'pat, 'tcx> {
1097
1104
Constant { value : mir:: Const < ' tcx > } ,
1098
1105
Range ( & ' pat PatRange < ' tcx > ) ,
1099
1106
Slice { len : usize , variable_length : bool } ,
1107
+ Never ,
1100
1108
Or { pats : Box < [ FlatPat < ' pat , ' tcx > ] > } ,
1101
1109
}
1102
1110
@@ -1156,6 +1164,9 @@ enum TestKind<'tcx> {
1156
1164
1157
1165
/// Test that the length of the slice is equal to `len`.
1158
1166
Len { len : u64 , op : BinOp } ,
1167
+
1168
+ /// Assert unreachability of never patterns.
1169
+ Never ,
1159
1170
}
1160
1171
1161
1172
/// A test to perform to determine which [`Candidate`] matches a value.
@@ -1569,6 +1580,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1569
1580
self . cfg . goto ( or_block, source_info, any_matches) ;
1570
1581
}
1571
1582
candidate. pre_binding_block = Some ( any_matches) ;
1583
+ } else {
1584
+ // Never subcandidates may have a set of bindings inconsistent with their siblings,
1585
+ // which would break later code. So we filter them out. Note that we can't filter out
1586
+ // top-level candidates this way.
1587
+ candidate. subcandidates . retain_mut ( |candidate| {
1588
+ if candidate. extra_data . is_never {
1589
+ candidate. visit_leaves ( |subcandidate| {
1590
+ let block = subcandidate. pre_binding_block . unwrap ( ) ;
1591
+ // That block is already unreachable but needs a terminator to make the MIR well-formed.
1592
+ let source_info = self . source_info ( subcandidate. extra_data . span ) ;
1593
+ self . cfg . terminate ( block, source_info, TerminatorKind :: Unreachable ) ;
1594
+ } ) ;
1595
+ false
1596
+ } else {
1597
+ true
1598
+ }
1599
+ } ) ;
1600
+ if candidate. subcandidates . is_empty ( ) {
1601
+ // If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`.
1602
+ candidate. pre_binding_block = Some ( self . cfg . start_new_block ( ) ) ;
1603
+ }
1572
1604
}
1573
1605
}
1574
1606
@@ -1990,6 +2022,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1990
2022
block = fresh_block;
1991
2023
}
1992
2024
2025
+ if candidate. extra_data . is_never {
2026
+ // This arm has a dummy body, we don't need to generate code for it. `block` is already
2027
+ // unreachable (except via false edge).
2028
+ let source_info = self . source_info ( candidate. extra_data . span ) ;
2029
+ self . cfg . terminate ( block, source_info, TerminatorKind :: Unreachable ) ;
2030
+ return self . cfg . start_new_block ( ) ;
2031
+ }
2032
+
1993
2033
self . ascribe_types (
1994
2034
block,
1995
2035
parent_data
0 commit comments