@@ -425,16 +425,12 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
425425 }
426426
427427 /// This computes `S(constructor, self)`. See top of the file for explanations.
428- fn specialize_constructor < ' a , ' q > (
428+ fn specialize_constructor (
429429 & self ,
430- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
430+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
431431 constructor : & Constructor < ' tcx > ,
432- ctor_wild_subpatterns : & [ & ' q Pat < ' tcx > ] ,
433- ) -> Option < PatStack < ' q , ' tcx > >
434- where
435- ' a : ' q ,
436- ' p : ' q ,
437- {
432+ ctor_wild_subpatterns : & ' p [ Pat < ' tcx > ] ,
433+ ) -> Option < PatStack < ' p , ' tcx > > {
438434 let new_heads = specialize_one_pattern ( cx, self . head ( ) , constructor, ctor_wild_subpatterns) ;
439435 new_heads. map ( |mut new_head| {
440436 new_head. 0 . extend_from_slice ( & self . 0 [ 1 ..] ) ;
@@ -459,6 +455,7 @@ impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> {
459455}
460456
461457/// A 2D matrix.
458+ #[ derive( Clone ) ]
462459pub struct Matrix < ' p , ' tcx > ( Vec < PatStack < ' p , ' tcx > > ) ;
463460
464461impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
@@ -486,16 +483,12 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
486483 }
487484
488485 /// This computes `S(constructor, self)`. See top of the file for explanations.
489- fn specialize_constructor < ' a , ' q > (
486+ fn specialize_constructor (
490487 & self ,
491- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
488+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
492489 constructor : & Constructor < ' tcx > ,
493- ctor_wild_subpatterns : & [ & ' q Pat < ' tcx > ] ,
494- ) -> Matrix < ' q , ' tcx >
495- where
496- ' a : ' q ,
497- ' p : ' q ,
498- {
490+ ctor_wild_subpatterns : & ' p [ Pat < ' tcx > ] ,
491+ ) -> Matrix < ' p , ' tcx > {
499492 self . 0
500493 . iter ( )
501494 . filter_map ( |r| r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns) )
@@ -1033,17 +1026,19 @@ impl<'tcx> Constructor<'tcx> {
10331026}
10341027
10351028#[ derive( Clone , Debug ) ]
1036- pub enum Usefulness < ' tcx > {
1037- Useful ,
1029+ pub enum Usefulness < ' tcx , ' p > {
1030+ /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
1031+ Useful ( Vec < & ' p Pat < ' tcx > > ) ,
1032+ /// Carries a list of witnesses of non-exhaustiveness.
10381033 UsefulWithWitness ( Vec < Witness < ' tcx > > ) ,
10391034 NotUseful ,
10401035}
10411036
1042- impl < ' tcx > Usefulness < ' tcx > {
1037+ impl < ' tcx , ' p > Usefulness < ' tcx , ' p > {
10431038 fn new_useful ( preference : WitnessPreference ) -> Self {
10441039 match preference {
10451040 ConstructWitness => UsefulWithWitness ( vec ! [ Witness ( vec![ ] ) ] ) ,
1046- LeaveOutWitness => Useful ,
1041+ LeaveOutWitness => Useful ( vec ! [ ] ) ,
10471042 }
10481043 }
10491044
@@ -1604,13 +1599,13 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
16041599/// relation to preceding patterns, it is not reachable) and exhaustiveness
16051600/// checking (if a wildcard pattern is useful in relation to a matrix, the
16061601/// matrix isn't exhaustive).
1607- pub fn is_useful < ' p , ' a , ' tcx > (
1608- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
1602+ pub fn is_useful < ' p , ' tcx > (
1603+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
16091604 matrix : & Matrix < ' p , ' tcx > ,
1610- v : & PatStack < ' _ , ' tcx > ,
1605+ v : & PatStack < ' p , ' tcx > ,
16111606 witness_preference : WitnessPreference ,
16121607 hir_id : HirId ,
1613- ) -> Usefulness < ' tcx > {
1608+ ) -> Usefulness < ' tcx , ' p > {
16141609 let & Matrix ( ref rows) = matrix;
16151610 debug ! ( "is_useful({:#?}, {:#?})" , matrix, v) ;
16161611
@@ -1631,11 +1626,26 @@ pub fn is_useful<'p, 'a, 'tcx>(
16311626
16321627 // If the first pattern is an or-pattern, expand it.
16331628 if let Some ( vs) = v. expand_or_pat ( ) {
1634- return vs
1635- . into_iter ( )
1636- . map ( |v| is_useful ( cx, matrix, & v, witness_preference, hir_id) )
1637- . find ( |result| result. is_useful ( ) )
1638- . unwrap_or ( NotUseful ) ;
1629+ // We need to push the already-seen patterns into the matrix in order to detect redundant
1630+ // branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns.
1631+ let mut matrix = matrix. clone ( ) ;
1632+ let mut unreachable_pats = Vec :: new ( ) ;
1633+ let mut any_is_useful = false ;
1634+ for v in vs {
1635+ let res = is_useful ( cx, & matrix, & v, witness_preference, hir_id) ;
1636+ match res {
1637+ Useful ( pats) => {
1638+ any_is_useful = true ;
1639+ unreachable_pats. extend ( pats) ;
1640+ }
1641+ NotUseful => unreachable_pats. push ( v. head ( ) ) ,
1642+ UsefulWithWitness ( _) => {
1643+ bug ! ( "Encountered or-pat in `v` during exhaustiveness checking" )
1644+ }
1645+ }
1646+ matrix. push ( v) ;
1647+ }
1648+ return if any_is_useful { Useful ( unreachable_pats) } else { NotUseful } ;
16391649 }
16401650
16411651 let ( ty, span) = matrix
@@ -1768,21 +1778,21 @@ pub fn is_useful<'p, 'a, 'tcx>(
17681778
17691779/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
17701780/// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
1771- fn is_useful_specialized < ' p , ' a , ' tcx > (
1772- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
1781+ fn is_useful_specialized < ' p , ' tcx > (
1782+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
17731783 matrix : & Matrix < ' p , ' tcx > ,
1774- v : & PatStack < ' _ , ' tcx > ,
1784+ v : & PatStack < ' p , ' tcx > ,
17751785 ctor : Constructor < ' tcx > ,
17761786 lty : Ty < ' tcx > ,
17771787 witness_preference : WitnessPreference ,
17781788 hir_id : HirId ,
1779- ) -> Usefulness < ' tcx > {
1789+ ) -> Usefulness < ' tcx , ' p > {
17801790 debug ! ( "is_useful_specialized({:#?}, {:#?}, {:?})" , v, ctor, lty) ;
17811791
1782- let ctor_wild_subpatterns_owned : Vec < _ > = ctor . wildcard_subpatterns ( cx , lty ) ;
1783- let ctor_wild_subpatterns : Vec < _ > = ctor_wild_subpatterns_owned . iter ( ) . collect ( ) ;
1784- let matrix = matrix. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns) ;
1785- v. specialize_constructor ( cx, & ctor, & ctor_wild_subpatterns)
1792+ let ctor_wild_subpatterns =
1793+ cx . pattern_arena . alloc_from_iter ( ctor . wildcard_subpatterns ( cx , lty ) ) ;
1794+ let matrix = matrix. specialize_constructor ( cx, & ctor, ctor_wild_subpatterns) ;
1795+ v. specialize_constructor ( cx, & ctor, ctor_wild_subpatterns)
17861796 . map ( |v| is_useful ( cx, & matrix, & v, witness_preference, hir_id) )
17871797 . map ( |u| u. apply_constructor ( cx, & ctor, lty) )
17881798 . unwrap_or ( NotUseful )
@@ -2250,13 +2260,13 @@ fn constructor_covered_by_range<'tcx>(
22502260 if intersects { Some ( ( ) ) } else { None }
22512261}
22522262
2253- fn patterns_for_variant < ' p , ' a : ' p , ' tcx > (
2254- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
2263+ fn patterns_for_variant < ' p , ' tcx > (
2264+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
22552265 subpatterns : & ' p [ FieldPat < ' tcx > ] ,
2256- ctor_wild_subpatterns : & [ & ' p Pat < ' tcx > ] ,
2266+ ctor_wild_subpatterns : & ' p [ Pat < ' tcx > ] ,
22572267 is_non_exhaustive : bool ,
22582268) -> PatStack < ' p , ' tcx > {
2259- let mut result = SmallVec :: from_slice ( ctor_wild_subpatterns) ;
2269+ let mut result: SmallVec < _ > = ctor_wild_subpatterns. iter ( ) . collect ( ) ;
22602270
22612271 for subpat in subpatterns {
22622272 if !is_non_exhaustive || !cx. is_uninhabited ( subpat. pattern . ty ) {
@@ -2280,11 +2290,11 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
22802290/// different patterns.
22812291/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
22822292/// fields filled with wild patterns.
2283- fn specialize_one_pattern < ' p , ' a : ' p , ' q : ' p , ' tcx > (
2284- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
2285- pat : & ' q Pat < ' tcx > ,
2293+ fn specialize_one_pattern < ' p , ' tcx > (
2294+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
2295+ pat : & ' p Pat < ' tcx > ,
22862296 constructor : & Constructor < ' tcx > ,
2287- ctor_wild_subpatterns : & [ & ' p Pat < ' tcx > ] ,
2297+ ctor_wild_subpatterns : & ' p [ Pat < ' tcx > ] ,
22882298) -> Option < PatStack < ' p , ' tcx > > {
22892299 if let NonExhaustive = constructor {
22902300 // Only a wildcard pattern can match the special extra constructor
@@ -2294,9 +2304,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
22942304 let result = match * pat. kind {
22952305 PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
22962306
2297- PatKind :: Binding { .. } | PatKind :: Wild => {
2298- Some ( PatStack :: from_slice ( ctor_wild_subpatterns) )
2299- }
2307+ PatKind :: Binding { .. } | PatKind :: Wild => Some ( ctor_wild_subpatterns. iter ( ) . collect ( ) ) ,
23002308
23012309 PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
23022310 let ref variant = adt_def. variants [ variant_index] ;
@@ -2406,7 +2414,6 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
24062414 . chain (
24072415 ctor_wild_subpatterns
24082416 . iter ( )
2409- . map ( |p| * p)
24102417 . skip ( prefix. len ( ) )
24112418 . take ( slice_count)
24122419 . chain ( suffix. iter ( ) ) ,
0 commit comments