@@ -1016,6 +1016,9 @@ struct PatternExtraData<'tcx> {
1016
1016
1017
1017
/// Types that must be asserted.
1018
1018
ascriptions : Vec < Ascription < ' tcx > > ,
1019
+
1020
+ /// Whether this corresponds to a never pattern.
1021
+ is_never : bool ,
1019
1022
}
1020
1023
1021
1024
impl < ' tcx > PatternExtraData < ' tcx > {
@@ -1041,12 +1044,14 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
1041
1044
pattern : & ' pat Pat < ' tcx > ,
1042
1045
cx : & mut Builder < ' _ , ' tcx > ,
1043
1046
) -> Self {
1047
+ let is_never = pattern. is_never_pattern ( ) ;
1044
1048
let mut flat_pat = FlatPat {
1045
1049
match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
1046
1050
extra_data : PatternExtraData {
1047
1051
span : pattern. span ,
1048
1052
bindings : Vec :: new ( ) ,
1049
1053
ascriptions : Vec :: new ( ) ,
1054
+ is_never,
1050
1055
} ,
1051
1056
} ;
1052
1057
cx. simplify_match_pairs ( & mut flat_pat. match_pairs , & mut flat_pat. extra_data ) ;
@@ -1062,6 +1067,8 @@ struct Candidate<'pat, 'tcx> {
1062
1067
match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
1063
1068
1064
1069
/// ...and if this is non-empty, one of these subcandidates also has to match...
1070
+ // Invariant: at the end of the algorithm, this must never contain a `is_never` candidate
1071
+ // because that would break binding consistency.
1065
1072
subcandidates : Vec < Candidate < ' pat , ' tcx > > ,
1066
1073
1067
1074
/// ...and the guard must be evaluated if there is one.
@@ -1172,6 +1179,7 @@ enum TestCase<'pat, 'tcx> {
1172
1179
Range ( & ' pat PatRange < ' tcx > ) ,
1173
1180
Slice { len : usize , variable_length : bool } ,
1174
1181
Deref { temp : Place < ' tcx > , mutability : Mutability } ,
1182
+ Never ,
1175
1183
Or { pats : Box < [ FlatPat < ' pat , ' tcx > ] > } ,
1176
1184
}
1177
1185
@@ -1238,6 +1246,9 @@ enum TestKind<'tcx> {
1238
1246
temp : Place < ' tcx > ,
1239
1247
mutability : Mutability ,
1240
1248
} ,
1249
+
1250
+ /// Assert unreachability of never patterns.
1251
+ Never ,
1241
1252
}
1242
1253
1243
1254
/// A test to perform to determine which [`Candidate`] matches a value.
@@ -1662,6 +1673,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1662
1673
self . cfg . goto ( or_block, source_info, any_matches) ;
1663
1674
}
1664
1675
candidate. pre_binding_block = Some ( any_matches) ;
1676
+ } else {
1677
+ // Never subcandidates may have a set of bindings inconsistent with their siblings,
1678
+ // which would break later code. So we filter them out. Note that we can't filter out
1679
+ // top-level candidates this way.
1680
+ candidate. subcandidates . retain_mut ( |candidate| {
1681
+ if candidate. extra_data . is_never {
1682
+ candidate. visit_leaves ( |subcandidate| {
1683
+ let block = subcandidate. pre_binding_block . unwrap ( ) ;
1684
+ // That block is already unreachable but needs a terminator to make the MIR well-formed.
1685
+ let source_info = self . source_info ( subcandidate. extra_data . span ) ;
1686
+ self . cfg . terminate ( block, source_info, TerminatorKind :: Unreachable ) ;
1687
+ } ) ;
1688
+ false
1689
+ } else {
1690
+ true
1691
+ }
1692
+ } ) ;
1693
+ if candidate. subcandidates . is_empty ( ) {
1694
+ // If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`.
1695
+ candidate. pre_binding_block = Some ( self . cfg . start_new_block ( ) ) ;
1696
+ }
1665
1697
}
1666
1698
}
1667
1699
@@ -2008,6 +2040,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2008
2040
block = fresh_block;
2009
2041
}
2010
2042
2043
+ if candidate. extra_data . is_never {
2044
+ // This arm has a dummy body, we don't need to generate code for it. `block` is already
2045
+ // unreachable (except via false edge).
2046
+ let source_info = self . source_info ( candidate. extra_data . span ) ;
2047
+ self . cfg . terminate ( block, source_info, TerminatorKind :: Unreachable ) ;
2048
+ return self . cfg . start_new_block ( ) ;
2049
+ }
2050
+
2011
2051
self . ascribe_types (
2012
2052
block,
2013
2053
parent_data
0 commit comments