@@ -463,12 +463,17 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
463
463
/// A 2D matrix.
464
464
#[ derive( Clone ) ]
465
465
struct Matrix < ' p , ' tcx > {
466
+ /// The rows of this matrix.
467
+ /// Invariant: `row.head()` is never an or-pattern.
466
468
rows : Vec < PatStack < ' p , ' tcx > > ,
469
+ /// Fake row that stores wildcard patterns that match the other rows. This is used only to track
470
+ /// the type and number of columns of the matrix.
471
+ wildcard_row : PatStack < ' p , ' tcx > ,
467
472
}
468
473
469
474
impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
470
- fn empty ( ) -> Self {
471
- Matrix { rows : vec ! [ ] }
475
+ fn empty ( wildcard_row : PatStack < ' p , ' tcx > ) -> Self {
476
+ Matrix { rows : vec ! [ ] , wildcard_row }
472
477
}
473
478
474
479
fn len ( & self ) -> usize {
@@ -477,25 +482,43 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
477
482
478
483
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
479
484
/// expands it.
480
- fn push ( & mut self , row : PatStack < ' p , ' tcx > ) -> usize {
485
+ fn push ( & mut self , row : PatStack < ' p , ' tcx > ) {
481
486
if !row. is_empty ( ) && row. head ( ) . is_or_pat ( ) {
482
- let mut count = 0 ;
483
487
for new_row in row. expand_or_pat ( ) {
484
- count += self . push ( new_row) ;
488
+ self . push ( new_row) ;
485
489
}
486
- count
487
490
} else {
488
491
self . rows . push ( row) ;
489
- 1
490
492
}
491
493
}
492
494
495
+ fn column_count ( & self ) -> usize {
496
+ self . wildcard_row . len ( )
497
+ }
498
+ fn head_ty ( & self ) -> Ty < ' tcx > {
499
+ let mut ty = self . wildcard_row . head ( ) . ty ( ) ;
500
+ // Opaque types can't get destructured/split, but the patterns can
501
+ // actually hint at hidden types, so we use the patterns' types instead.
502
+ if let ty:: Alias ( ty:: Opaque , ..) = ty. kind ( ) {
503
+ if let Some ( row) = self . rows ( ) . next ( ) {
504
+ ty = row. head ( ) . ty ( ) ;
505
+ }
506
+ }
507
+ ty
508
+ }
509
+
493
510
fn rows < ' a > (
494
511
& ' a self ,
495
512
) -> impl Iterator < Item = & ' a PatStack < ' p , ' tcx > > + Clone + DoubleEndedIterator + ExactSizeIterator
496
513
{
497
514
self . rows . iter ( )
498
515
}
516
+ fn rows_mut < ' a > (
517
+ & ' a mut self ,
518
+ ) -> impl Iterator < Item = & ' a mut PatStack < ' p , ' tcx > > + DoubleEndedIterator + ExactSizeIterator
519
+ {
520
+ self . rows . iter_mut ( )
521
+ }
499
522
/// Iterate over the first component of each row
500
523
fn heads < ' a > (
501
524
& ' a self ,
@@ -509,7 +532,8 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
509
532
pcx : & PatCtxt < ' _ , ' p , ' tcx > ,
510
533
ctor : & Constructor < ' tcx > ,
511
534
) -> Matrix < ' p , ' tcx > {
512
- let mut matrix = Matrix :: empty ( ) ;
535
+ let mut matrix =
536
+ Matrix :: empty ( self . wildcard_row . pop_head_constructor ( pcx, ctor, usize:: MAX ) ) ;
513
537
for ( i, row) in self . rows ( ) . enumerate ( ) {
514
538
if ctor. is_covered_by ( pcx, row. head ( ) . ctor ( ) ) {
515
539
let new_row = row. pop_head_constructor ( pcx, ctor, i) ;
@@ -741,18 +765,17 @@ impl<'tcx> WitnessMatrix<'tcx> {
741
765
fn compute_usefulness < ' p , ' tcx > (
742
766
cx : & MatchCheckCtxt < ' p , ' tcx > ,
743
767
matrix : & mut Matrix < ' p , ' tcx > ,
744
- v : & PatStack < ' p , ' tcx > ,
745
768
collect_witnesses : bool ,
746
769
lint_root : HirId ,
747
770
is_top_level : bool ,
748
771
) -> WitnessMatrix < ' tcx > {
749
- debug_assert ! ( matrix. rows( ) . all( |r| r. len( ) == v . len ( ) ) ) ;
772
+ debug_assert ! ( matrix. rows( ) . all( |r| r. len( ) == matrix . column_count ( ) ) ) ;
750
773
751
774
// The base case. We are pattern-matching on () and the return value is based on whether our
752
775
// matrix has a row or not.
753
- if v . is_empty ( ) {
776
+ if matrix . column_count ( ) == 0 {
754
777
let mut useful = true ;
755
- for row in matrix. rows . iter_mut ( ) {
778
+ for row in matrix. rows_mut ( ) {
756
779
row. is_useful = useful;
757
780
useful = useful && row. is_under_guard ;
758
781
if !useful {
@@ -766,14 +789,7 @@ fn compute_usefulness<'p, 'tcx>(
766
789
}
767
790
}
768
791
769
- let mut ty = v. head ( ) . ty ( ) ;
770
- // Opaque types can't get destructured/split, but the patterns can
771
- // actually hint at hidden types, so we use the patterns' types instead.
772
- if let ty:: Alias ( ty:: Opaque , ..) = ty. kind ( ) {
773
- if let Some ( row) = matrix. rows ( ) . next ( ) {
774
- ty = row. head ( ) . ty ( ) ;
775
- }
776
- }
792
+ let ty = matrix. head_ty ( ) ;
777
793
debug ! ( "ty: {ty:?}" ) ;
778
794
let pcx = & PatCtxt { cx, ty, span : DUMMY_SP , is_top_level } ;
779
795
@@ -870,9 +886,8 @@ fn compute_usefulness<'p, 'tcx>(
870
886
|| matches ! ( ctor, Constructor :: Wildcard | Constructor :: Missing ) ) ;
871
887
debug ! ( "specialize({:?})" , ctor) ;
872
888
let mut spec_matrix = matrix. specialize_constructor ( pcx, & ctor) ;
873
- let v = v. pop_head_constructor ( pcx, & ctor, usize:: MAX ) ;
874
889
let mut witnesses = ensure_sufficient_stack ( || {
875
- compute_usefulness ( cx, & mut spec_matrix, & v , collect_witnesses, lint_root, false )
890
+ compute_usefulness ( cx, & mut spec_matrix, collect_witnesses, lint_root, false )
876
891
} ) ;
877
892
if collect_witnesses {
878
893
witnesses. apply_constructor ( pcx, & missing_ctors, & ctor) ;
@@ -1009,16 +1024,15 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
1009
1024
scrut_ty : Ty < ' tcx > ,
1010
1025
scrut_span : Span ,
1011
1026
) -> UsefulnessReport < ' p , ' tcx > {
1012
- let mut matrix = Matrix :: empty ( ) ;
1027
+ let wild_pattern = cx. pattern_arena . alloc ( DeconstructedPat :: wildcard ( scrut_ty, DUMMY_SP ) ) ;
1028
+ let wildcard_row = PatStack :: from_pattern ( wild_pattern, usize:: MAX , false ) ;
1029
+ let mut matrix = Matrix :: empty ( wildcard_row) ;
1013
1030
for ( row_id, arm) in arms. iter ( ) . enumerate ( ) {
1014
1031
let v = PatStack :: from_pattern ( arm. pat , row_id, arm. has_guard ) ;
1015
1032
matrix. push ( v) ;
1016
1033
}
1017
1034
1018
- let wild_pattern = cx. pattern_arena . alloc ( DeconstructedPat :: wildcard ( scrut_ty, DUMMY_SP ) ) ;
1019
- let v = PatStack :: from_pattern ( wild_pattern, usize:: MAX , false ) ;
1020
- let non_exhaustiveness_witnesses =
1021
- compute_usefulness ( cx, & mut matrix, & v, true , lint_root, true ) ;
1035
+ let non_exhaustiveness_witnesses = compute_usefulness ( cx, & mut matrix, true , lint_root, true ) ;
1022
1036
let non_exhaustiveness_witnesses: Vec < _ > = non_exhaustiveness_witnesses. single_column ( ) ;
1023
1037
let arm_usefulness: Vec < _ > = arms
1024
1038
. iter ( )
0 commit comments