@@ -567,39 +567,16 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
567567 }
568568}
569569
570- /// A row of the matrix. Represents a pattern-tuple under investigation.
570+ /// Represents a pattern-tuple under investigation.
571571#[ derive( Clone ) ]
572572struct PatStack < ' p , ' tcx > {
573573 // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well.
574574 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 ,
586575}
587576
588577impl < ' 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] }
603580 }
604581
605582 fn is_empty ( & self ) -> bool {
@@ -622,10 +599,9 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
622599 // an or-pattern. Panics if `self` is empty.
623600 fn expand_or_pat < ' a > ( & ' a self ) -> impl Iterator < Item = PatStack < ' p , ' tcx > > + Captures < ' a > {
624601 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 }
629605 } )
630606 }
631607
@@ -635,19 +611,18 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
635611 & self ,
636612 pcx : & PatCtxt < ' _ , ' p , ' tcx > ,
637613 ctor : & Constructor < ' tcx > ,
638- parent_row : usize ,
639614 ) -> PatStack < ' p , ' tcx > {
640615 // We pop the head pattern and push the new fields extracted from the arguments of
641616 // `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 }
645620 }
646621}
647622
648- /// Pretty-printing for a matrix row.
649623impl < ' p , ' tcx > fmt:: Debug for PatStack < ' p , ' tcx > {
650624 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
625+ // We pretty-print similarly to the `Debug` impl of `Matrix`.
651626 write ! ( f, "+" ) ?;
652627 for pat in self . iter ( ) {
653628 write ! ( f, " {pat:?} +" ) ?;
@@ -656,6 +631,74 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
656631 }
657632}
658633
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+
659702/// A 2D matrix. Represents a list of pattern-tuples under investigation.
660703///
661704/// 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> {
668711/// the matrix will correspond to `scrutinee.0.Some.0` and the second column to `scrutinee.1`.
669712#[ derive( Clone ) ]
670713struct Matrix < ' p , ' tcx > {
671- rows : Vec < PatStack < ' p , ' tcx > > ,
714+ rows : Vec < MatrixRow < ' p , ' tcx > > ,
672715 /// Stores an extra fictitious row full of wildcards. Mostly used to keep track of the type of
673716 /// each column. This must obey the same invariants as the real rows.
674717 wildcard_row : PatStack < ' p , ' tcx > ,
@@ -677,7 +720,7 @@ struct Matrix<'p, 'tcx> {
677720impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
678721 /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
679722 /// 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 > ) {
681724 if !row. is_empty ( ) && row. head ( ) . is_or_pat ( ) {
682725 // Expand nested or-patterns.
683726 for new_row in row. expand_or_pat ( ) {
@@ -698,10 +741,15 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
698741 ' p : ' a ,
699742 {
700743 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) ;
702745 let mut matrix = Matrix { rows : vec ! [ ] , wildcard_row } ;
703746 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+ } ;
705753 matrix. expand_and_push ( v) ;
706754 }
707755 matrix
@@ -733,13 +781,13 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
733781
734782 fn rows < ' a > (
735783 & ' a self ,
736- ) -> impl Iterator < Item = & ' a PatStack < ' p , ' tcx > > + Clone + DoubleEndedIterator + ExactSizeIterator
784+ ) -> impl Iterator < Item = & ' a MatrixRow < ' p , ' tcx > > + Clone + DoubleEndedIterator + ExactSizeIterator
737785 {
738786 self . rows . iter ( )
739787 }
740788 fn rows_mut < ' a > (
741789 & ' 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
743791 {
744792 self . rows . iter_mut ( )
745793 }
@@ -757,7 +805,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
757805 pcx : & PatCtxt < ' _ , ' p , ' tcx > ,
758806 ctor : & Constructor < ' tcx > ,
759807 ) -> 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) ;
761809 let mut matrix = Matrix { rows : vec ! [ ] , wildcard_row } ;
762810 for ( i, row) in self . rows ( ) . enumerate ( ) {
763811 if ctor. is_covered_by ( pcx, row. head ( ) . ctor ( ) ) {
0 commit comments