@@ -1016,6 +1016,9 @@ struct PatternExtraData<'tcx> {
10161016
10171017 /// Types that must be asserted.
10181018 ascriptions : Vec < Ascription < ' tcx > > ,
1019+
1020+ /// Whether this corresponds to a never pattern.
1021+ is_never : bool ,
10191022}
10201023
10211024impl < ' tcx > PatternExtraData < ' tcx > {
@@ -1041,12 +1044,14 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
10411044 pattern : & ' pat Pat < ' tcx > ,
10421045 cx : & mut Builder < ' _ , ' tcx > ,
10431046 ) -> Self {
1047+ let is_never = pattern. is_never_pattern ( ) ;
10441048 let mut flat_pat = FlatPat {
10451049 match_pairs : vec ! [ MatchPair :: new( place, pattern, cx) ] ,
10461050 extra_data : PatternExtraData {
10471051 span : pattern. span ,
10481052 bindings : Vec :: new ( ) ,
10491053 ascriptions : Vec :: new ( ) ,
1054+ is_never,
10501055 } ,
10511056 } ;
10521057 cx. simplify_match_pairs ( & mut flat_pat. match_pairs , & mut flat_pat. extra_data ) ;
@@ -1062,6 +1067,8 @@ struct Candidate<'pat, 'tcx> {
10621067 match_pairs : Vec < MatchPair < ' pat , ' tcx > > ,
10631068
10641069 /// ...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.
10651072 subcandidates : Vec < Candidate < ' pat , ' tcx > > ,
10661073
10671074 /// ...and the guard must be evaluated if there is one.
@@ -1172,6 +1179,7 @@ enum TestCase<'pat, 'tcx> {
11721179 Range ( & ' pat PatRange < ' tcx > ) ,
11731180 Slice { len : usize , variable_length : bool } ,
11741181 Deref { temp : Place < ' tcx > , mutability : Mutability } ,
1182+ Never ,
11751183 Or { pats : Box < [ FlatPat < ' pat , ' tcx > ] > } ,
11761184}
11771185
@@ -1238,6 +1246,9 @@ enum TestKind<'tcx> {
12381246 temp : Place < ' tcx > ,
12391247 mutability : Mutability ,
12401248 } ,
1249+
1250+ /// Assert unreachability of never patterns.
1251+ Never ,
12411252}
12421253
12431254/// A test to perform to determine which [`Candidate`] matches a value.
@@ -1662,6 +1673,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16621673 self . cfg . goto ( or_block, source_info, any_matches) ;
16631674 }
16641675 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+ }
16651697 }
16661698 }
16671699
@@ -2008,6 +2040,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20082040 block = fresh_block;
20092041 }
20102042
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+
20112051 self . ascribe_types (
20122052 block,
20132053 parent_data
0 commit comments