@@ -567,39 +567,16 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
567
567
}
568
568
}
569
569
570
- /// A row of the matrix. Represents a pattern-tuple under investigation.
570
+ /// Represents a pattern-tuple under investigation.
571
571
#[ derive( Clone ) ]
572
572
struct PatStack < ' p , ' tcx > {
573
573
// Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well.
574
574
pats : SmallVec < [ & ' p DeconstructedPat < ' p , ' tcx > ; 2 ] > ,
575
- /// Whether the original arm had a guard.
576
- is_under_guard : bool ,
577
- /// When we specialize, we remember which row of the original matrix produced a given row of the
578
- /// specialized matrix. When we unspecialize, we use this to propagate reachability back up the
579
- /// callstack.
580
- /// At the start of the algorithm, this is the id of the arm this comes from (but we don't use
581
- /// this fact anywhere).
582
- parent_row : usize ,
583
- /// False when the matrix is just built. This is set to `true` by
584
- /// [`compute_exhaustiveness_and_reachability`] if the arm is found to be reachable.
585
- reachable : bool ,
586
575
}
587
576
588
577
impl < ' p , ' tcx > PatStack < ' p , ' tcx > {
589
- fn from_pattern (
590
- pat : & ' p DeconstructedPat < ' p , ' tcx > ,
591
- parent_row : usize ,
592
- is_under_guard : bool ,
593
- ) -> Self {
594
- PatStack { pats : smallvec ! [ pat] , parent_row, is_under_guard, reachable : false }
595
- }
596
-
597
- fn from_vec (
598
- pats : SmallVec < [ & ' p DeconstructedPat < ' p , ' tcx > ; 2 ] > ,
599
- parent_row : usize ,
600
- is_under_guard : bool ,
601
- ) -> Self {
602
- PatStack { pats, parent_row, is_under_guard, reachable : false }
578
+ fn from_pattern ( pat : & ' p DeconstructedPat < ' p , ' tcx > ) -> Self {
579
+ PatStack { pats : smallvec ! [ pat] }
603
580
}
604
581
605
582
fn is_empty ( & self ) -> bool {
@@ -622,10 +599,9 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
622
599
// an or-pattern. Panics if `self` is empty.
623
600
fn expand_or_pat < ' a > ( & ' a self ) -> impl Iterator < Item = PatStack < ' p , ' tcx > > + Captures < ' a > {
624
601
self . head ( ) . flatten_or_pat ( ) . into_iter ( ) . map ( move |pat| {
625
- let mut new_patstack =
626
- PatStack :: from_pattern ( pat, self . parent_row , self . is_under_guard ) ;
627
- new_patstack. pats . extend_from_slice ( & self . pats [ 1 ..] ) ;
628
- new_patstack
602
+ let mut new_pats = smallvec ! [ pat] ;
603
+ new_pats. extend_from_slice ( & self . pats [ 1 ..] ) ;
604
+ PatStack { pats : new_pats }
629
605
} )
630
606
}
631
607
@@ -635,19 +611,18 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
635
611
& self ,
636
612
pcx : & PatCtxt < ' _ , ' p , ' tcx > ,
637
613
ctor : & Constructor < ' tcx > ,
638
- parent_row : usize ,
639
614
) -> PatStack < ' p , ' tcx > {
640
615
// We pop the head pattern and push the new fields extracted from the arguments of
641
616
// `self.head()`.
642
- let mut new_fields : SmallVec < [ _ ; 2 ] > = self . head ( ) . specialize ( pcx, ctor) ;
643
- new_fields . extend_from_slice ( & self . pats [ 1 ..] ) ;
644
- PatStack :: from_vec ( new_fields , parent_row , self . is_under_guard )
617
+ let mut new_pats = self . head ( ) . specialize ( pcx, ctor) ;
618
+ new_pats . extend_from_slice ( & self . pats [ 1 ..] ) ;
619
+ PatStack { pats : new_pats }
645
620
}
646
621
}
647
622
648
- /// Pretty-printing for a matrix row.
649
623
impl < ' p , ' tcx > fmt:: Debug for PatStack < ' p , ' tcx > {
650
624
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
625
+ // We pretty-print similarly to the `Debug` impl of `Matrix`.
651
626
write ! ( f, "+" ) ?;
652
627
for pat in self . iter ( ) {
653
628
write ! ( f, " {pat:?} +" ) ?;
@@ -656,6 +631,74 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
656
631
}
657
632
}
658
633
634
+ /// A row of the matrix.
635
+ #[ derive( Clone ) ]
636
+ struct MatrixRow < ' p , ' tcx > {
637
+ // The patterns in the row.
638
+ pats : PatStack < ' p , ' tcx > ,
639
+ /// Whether the original arm had a guard. This is inherited when specializing.
640
+ is_under_guard : bool ,
641
+ /// When we specialize, we remember which row of the original matrix produced a given row of the
642
+ /// specialized matrix. When we unspecialize, we use this to propagate reachability back up the
643
+ /// callstack.
644
+ parent_row : usize ,
645
+ /// False when the matrix is just built. This is set to `true` by
646
+ /// [`compute_exhaustiveness_and_reachability`] if the arm is found to be reachable.
647
+ /// This is reset to `false` when specializing.
648
+ reachable : bool ,
649
+ }
650
+
651
+ impl < ' p , ' tcx > MatrixRow < ' p , ' tcx > {
652
+ fn is_empty ( & self ) -> bool {
653
+ self . pats . is_empty ( )
654
+ }
655
+
656
+ fn len ( & self ) -> usize {
657
+ self . pats . len ( )
658
+ }
659
+
660
+ fn head ( & self ) -> & ' p DeconstructedPat < ' p , ' tcx > {
661
+ self . pats . head ( )
662
+ }
663
+
664
+ fn iter ( & self ) -> impl Iterator < Item = & DeconstructedPat < ' p , ' tcx > > {
665
+ self . pats . iter ( )
666
+ }
667
+
668
+ // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is
669
+ // an or-pattern. Panics if `self` is empty.
670
+ fn expand_or_pat < ' a > ( & ' a self ) -> impl Iterator < Item = MatrixRow < ' p , ' tcx > > + Captures < ' a > {
671
+ self . pats . expand_or_pat ( ) . map ( |patstack| MatrixRow {
672
+ pats : patstack,
673
+ parent_row : self . parent_row ,
674
+ is_under_guard : self . is_under_guard ,
675
+ reachable : false ,
676
+ } )
677
+ }
678
+
679
+ /// This computes `specialize(ctor, self)`. See top of the file for explanations.
680
+ /// Only call if `ctor.is_covered_by(self.head().ctor())` is true.
681
+ fn pop_head_constructor (
682
+ & self ,
683
+ pcx : & PatCtxt < ' _ , ' p , ' tcx > ,
684
+ ctor : & Constructor < ' tcx > ,
685
+ parent_row : usize ,
686
+ ) -> MatrixRow < ' p , ' tcx > {
687
+ MatrixRow {
688
+ pats : self . pats . pop_head_constructor ( pcx, ctor) ,
689
+ parent_row,
690
+ is_under_guard : self . is_under_guard ,
691
+ reachable : false ,
692
+ }
693
+ }
694
+ }
695
+
696
+ impl < ' p , ' tcx > fmt:: Debug for MatrixRow < ' p , ' tcx > {
697
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
698
+ self . pats . fmt ( f)
699
+ }
700
+ }
701
+
659
702
/// A 2D matrix. Represents a list of pattern-tuples under investigation.
660
703
///
661
704
/// Invariant: each row must have the same length, and each column must have the same type.
@@ -668,7 +711,7 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
668
711
/// the matrix will correspond to `scrutinee.0.Some.0` and the second column to `scrutinee.1`.
669
712
#[ derive( Clone ) ]
670
713
struct Matrix < ' p , ' tcx > {
671
- rows : Vec < PatStack < ' p , ' tcx > > ,
714
+ rows : Vec < MatrixRow < ' p , ' tcx > > ,
672
715
/// Stores an extra fictitious row full of wildcards. Mostly used to keep track of the type of
673
716
/// each column. This must obey the same invariants as the real rows.
674
717
wildcard_row : PatStack < ' p , ' tcx > ,
@@ -677,7 +720,7 @@ struct Matrix<'p, 'tcx> {
677
720
impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
678
721
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
679
722
/// expands it. Internal method, prefer [`Matrix::new`].
680
- fn expand_and_push ( & mut self , row : PatStack < ' p , ' tcx > ) {
723
+ fn expand_and_push ( & mut self , row : MatrixRow < ' p , ' tcx > ) {
681
724
if !row. is_empty ( ) && row. head ( ) . is_or_pat ( ) {
682
725
// Expand nested or-patterns.
683
726
for new_row in row. expand_or_pat ( ) {
@@ -698,10 +741,15 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
698
741
' p : ' a ,
699
742
{
700
743
let wild_pattern = cx. pattern_arena . alloc ( DeconstructedPat :: wildcard ( scrut_ty, DUMMY_SP ) ) ;
701
- let wildcard_row = PatStack :: from_pattern ( wild_pattern, usize :: MAX , false ) ;
744
+ let wildcard_row = PatStack :: from_pattern ( wild_pattern) ;
702
745
let mut matrix = Matrix { rows : vec ! [ ] , wildcard_row } ;
703
746
for ( row_id, arm) in iter. enumerate ( ) {
704
- let v = PatStack :: from_pattern ( arm. pat , row_id, arm. has_guard ) ;
747
+ let v = MatrixRow {
748
+ pats : PatStack :: from_pattern ( arm. pat ) ,
749
+ parent_row : row_id, // dummy, we won't read it
750
+ is_under_guard : arm. has_guard ,
751
+ reachable : false ,
752
+ } ;
705
753
matrix. expand_and_push ( v) ;
706
754
}
707
755
matrix
@@ -733,13 +781,13 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
733
781
734
782
fn rows < ' a > (
735
783
& ' a self ,
736
- ) -> impl Iterator < Item = & ' a PatStack < ' p , ' tcx > > + Clone + DoubleEndedIterator + ExactSizeIterator
784
+ ) -> impl Iterator < Item = & ' a MatrixRow < ' p , ' tcx > > + Clone + DoubleEndedIterator + ExactSizeIterator
737
785
{
738
786
self . rows . iter ( )
739
787
}
740
788
fn rows_mut < ' a > (
741
789
& ' a mut self ,
742
- ) -> impl Iterator < Item = & ' a mut PatStack < ' p , ' tcx > > + DoubleEndedIterator + ExactSizeIterator
790
+ ) -> impl Iterator < Item = & ' a mut MatrixRow < ' p , ' tcx > > + DoubleEndedIterator + ExactSizeIterator
743
791
{
744
792
self . rows . iter_mut ( )
745
793
}
@@ -757,7 +805,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
757
805
pcx : & PatCtxt < ' _ , ' p , ' tcx > ,
758
806
ctor : & Constructor < ' tcx > ,
759
807
) -> Matrix < ' p , ' tcx > {
760
- let wildcard_row = self . wildcard_row . pop_head_constructor ( pcx, ctor, usize :: MAX ) ;
808
+ let wildcard_row = self . wildcard_row . pop_head_constructor ( pcx, ctor) ;
761
809
let mut matrix = Matrix { rows : vec ! [ ] , wildcard_row } ;
762
810
for ( i, row) in self . rows ( ) . enumerate ( ) {
763
811
if ctor. is_covered_by ( pcx, row. head ( ) . ctor ( ) ) {
0 commit comments