@@ -947,6 +947,9 @@ struct PatternExtraData<'tcx> {
947947
948948 /// Types that must be asserted.
949949 ascriptions : Vec < Ascription < ' tcx > > ,
950+
951+ /// Whether this corresponds to a never pattern.
952+ is_never : bool ,
950953}
951954
952955impl < ' tcx > PatternExtraData < ' tcx > {
@@ -972,12 +975,14 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
972975 pattern : & ' pat Pat < ' tcx > ,
973976 cx : & mut Builder < ' _ , ' tcx > ,
974977 ) -> Self {
978+ let is_never = pattern. is_never_pattern ( ) ;
975979 let mut flat_pat = FlatPat {
976980 match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
977981 extra_data : PatternExtraData {
978982 span : pattern. span ,
979983 bindings : Vec :: new ( ) ,
980984 ascriptions : Vec :: new ( ) ,
985+ is_never,
981986 } ,
982987 } ;
983988 cx. simplify_match_pairs ( & mut flat_pat. match_pairs , & mut flat_pat. extra_data ) ;
@@ -993,6 +998,8 @@ struct Candidate<'pat, 'tcx> {
993998 match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
994999
9951000 /// ...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.
9961003 subcandidates : Vec < Candidate < ' pat , ' tcx > > ,
9971004
9981005 /// ...and the guard must be evaluated if there is one.
@@ -1097,6 +1104,7 @@ enum TestCase<'pat, 'tcx> {
10971104 Constant { value : mir:: Const < ' tcx > } ,
10981105 Range ( & ' pat PatRange < ' tcx > ) ,
10991106 Slice { len : usize , variable_length : bool } ,
1107+ Never ,
11001108 Or { pats : Box < [ FlatPat < ' pat , ' tcx > ] > } ,
11011109}
11021110
@@ -1156,6 +1164,9 @@ enum TestKind<'tcx> {
11561164
11571165 /// Test that the length of the slice is equal to `len`.
11581166 Len { len : u64 , op : BinOp } ,
1167+
1168+ /// Assert unreachability of never patterns.
1169+ Never ,
11591170}
11601171
11611172/// A test to perform to determine which [`Candidate`] matches a value.
@@ -1569,6 +1580,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
15691580 self . cfg . goto ( or_block, source_info, any_matches) ;
15701581 }
15711582 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+ }
15721604 }
15731605 }
15741606
@@ -1990,6 +2022,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19902022 block = fresh_block;
19912023 }
19922024
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+
19932033 self . ascribe_types (
19942034 block,
19952035 parent_data
0 commit comments