@@ -425,16 +425,12 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
425
425
}
426
426
427
427
/// This computes `S(constructor, self)`. See top of the file for explanations.
428
- fn specialize_constructor < ' a , ' q > (
428
+ fn specialize_constructor (
429
429
& self ,
430
- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
430
+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
431
431
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 > > {
438
434
let new_heads = specialize_one_pattern ( cx, self . head ( ) , constructor, ctor_wild_subpatterns) ;
439
435
new_heads. map ( |mut new_head| {
440
436
new_head. 0 . extend_from_slice ( & self . 0 [ 1 ..] ) ;
@@ -459,6 +455,7 @@ impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> {
459
455
}
460
456
461
457
/// A 2D matrix.
458
+ #[ derive( Clone ) ]
462
459
pub struct Matrix < ' p , ' tcx > ( Vec < PatStack < ' p , ' tcx > > ) ;
463
460
464
461
impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
@@ -486,16 +483,12 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
486
483
}
487
484
488
485
/// This computes `S(constructor, self)`. See top of the file for explanations.
489
- fn specialize_constructor < ' a , ' q > (
486
+ fn specialize_constructor (
490
487
& self ,
491
- cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
488
+ cx : & mut MatchCheckCtxt < ' p , ' tcx > ,
492
489
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 > {
499
492
self . 0
500
493
. iter ( )
501
494
. filter_map ( |r| r. specialize_constructor ( cx, constructor, ctor_wild_subpatterns) )
@@ -1033,17 +1026,19 @@ impl<'tcx> Constructor<'tcx> {
1033
1026
}
1034
1027
1035
1028
#[ 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.
1038
1033
UsefulWithWitness ( Vec < Witness < ' tcx > > ) ,
1039
1034
NotUseful ,
1040
1035
}
1041
1036
1042
- impl < ' tcx > Usefulness < ' tcx > {
1037
+ impl < ' tcx , ' p > Usefulness < ' tcx , ' p > {
1043
1038
fn new_useful ( preference : WitnessPreference ) -> Self {
1044
1039
match preference {
1045
1040
ConstructWitness => UsefulWithWitness ( vec ! [ Witness ( vec![ ] ) ] ) ,
1046
- LeaveOutWitness => Useful ,
1041
+ LeaveOutWitness => Useful ( vec ! [ ] ) ,
1047
1042
}
1048
1043
}
1049
1044
@@ -1604,13 +1599,13 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
1604
1599
/// relation to preceding patterns, it is not reachable) and exhaustiveness
1605
1600
/// checking (if a wildcard pattern is useful in relation to a matrix, the
1606
1601
/// 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 > ,
1609
1604
matrix : & Matrix < ' p , ' tcx > ,
1610
- v : & PatStack < ' _ , ' tcx > ,
1605
+ v : & PatStack < ' p , ' tcx > ,
1611
1606
witness_preference : WitnessPreference ,
1612
1607
hir_id : HirId ,
1613
- ) -> Usefulness < ' tcx > {
1608
+ ) -> Usefulness < ' tcx , ' p > {
1614
1609
let & Matrix ( ref rows) = matrix;
1615
1610
debug ! ( "is_useful({:#?}, {:#?})" , matrix, v) ;
1616
1611
@@ -1631,11 +1626,26 @@ pub fn is_useful<'p, 'a, 'tcx>(
1631
1626
1632
1627
// If the first pattern is an or-pattern, expand it.
1633
1628
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 } ;
1639
1649
}
1640
1650
1641
1651
let ( ty, span) = matrix
@@ -1768,21 +1778,21 @@ pub fn is_useful<'p, 'a, 'tcx>(
1768
1778
1769
1779
/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
1770
1780
/// 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 > ,
1773
1783
matrix : & Matrix < ' p , ' tcx > ,
1774
- v : & PatStack < ' _ , ' tcx > ,
1784
+ v : & PatStack < ' p , ' tcx > ,
1775
1785
ctor : Constructor < ' tcx > ,
1776
1786
lty : Ty < ' tcx > ,
1777
1787
witness_preference : WitnessPreference ,
1778
1788
hir_id : HirId ,
1779
- ) -> Usefulness < ' tcx > {
1789
+ ) -> Usefulness < ' tcx , ' p > {
1780
1790
debug ! ( "is_useful_specialized({:#?}, {:#?}, {:?})" , v, ctor, lty) ;
1781
1791
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)
1786
1796
. map ( |v| is_useful ( cx, & matrix, & v, witness_preference, hir_id) )
1787
1797
. map ( |u| u. apply_constructor ( cx, & ctor, lty) )
1788
1798
. unwrap_or ( NotUseful )
@@ -2250,13 +2260,13 @@ fn constructor_covered_by_range<'tcx>(
2250
2260
if intersects { Some ( ( ) ) } else { None }
2251
2261
}
2252
2262
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 > ,
2255
2265
subpatterns : & ' p [ FieldPat < ' tcx > ] ,
2256
- ctor_wild_subpatterns : & [ & ' p Pat < ' tcx > ] ,
2266
+ ctor_wild_subpatterns : & ' p [ Pat < ' tcx > ] ,
2257
2267
is_non_exhaustive : bool ,
2258
2268
) -> PatStack < ' p , ' tcx > {
2259
- let mut result = SmallVec :: from_slice ( ctor_wild_subpatterns) ;
2269
+ let mut result: SmallVec < _ > = ctor_wild_subpatterns. iter ( ) . collect ( ) ;
2260
2270
2261
2271
for subpat in subpatterns {
2262
2272
if !is_non_exhaustive || !cx. is_uninhabited ( subpat. pattern . ty ) {
@@ -2280,11 +2290,11 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
2280
2290
/// different patterns.
2281
2291
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
2282
2292
/// 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 > ,
2286
2296
constructor : & Constructor < ' tcx > ,
2287
- ctor_wild_subpatterns : & [ & ' p Pat < ' tcx > ] ,
2297
+ ctor_wild_subpatterns : & ' p [ Pat < ' tcx > ] ,
2288
2298
) -> Option < PatStack < ' p , ' tcx > > {
2289
2299
if let NonExhaustive = constructor {
2290
2300
// Only a wildcard pattern can match the special extra constructor
@@ -2294,9 +2304,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2294
2304
let result = match * pat. kind {
2295
2305
PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
2296
2306
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 ( ) ) ,
2300
2308
2301
2309
PatKind :: Variant { adt_def, variant_index, ref subpatterns, .. } => {
2302
2310
let ref variant = adt_def. variants [ variant_index] ;
@@ -2406,7 +2414,6 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2406
2414
. chain (
2407
2415
ctor_wild_subpatterns
2408
2416
. iter ( )
2409
- . map ( |p| * p)
2410
2417
. skip ( prefix. len ( ) )
2411
2418
. take ( slice_count)
2412
2419
. chain ( suffix. iter ( ) ) ,
0 commit comments