@@ -499,7 +499,7 @@ use crate::errors::{
499499
500500use rustc_data_structures:: captures:: Captures ;
501501
502- use rustc_arena:: TypedArena ;
502+ use rustc_arena:: { DroplessArena , TypedArena } ;
503503use rustc_data_structures:: stack:: ensure_sufficient_stack;
504504use rustc_hir:: def_id:: DefId ;
505505use rustc_hir:: HirId ;
@@ -508,8 +508,8 @@ use rustc_session::lint;
508508use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
509509use rustc_span:: { Span , DUMMY_SP } ;
510510
511- use smallvec:: { smallvec , SmallVec } ;
512- use std:: fmt;
511+ use smallvec:: SmallVec ;
512+ use std:: { fmt, iter :: once } ;
513513
514514pub ( crate ) struct MatchCheckCtxt < ' p , ' tcx > {
515515 pub ( crate ) tcx : TyCtxt < ' tcx > ,
@@ -521,6 +521,7 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
521521 pub ( crate ) module : DefId ,
522522 pub ( crate ) param_env : ty:: ParamEnv < ' tcx > ,
523523 pub ( crate ) pattern_arena : & ' p TypedArena < DeconstructedPat < ' p , ' tcx > > ,
524+ pub ( crate ) dropless_arena : & ' p DroplessArena ,
524525 /// Lint level at the match.
525526 pub ( crate ) match_lint_level : HirId ,
526527 /// The span of the whole match, if applicable.
@@ -570,13 +571,12 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
570571/// Represents a pattern-tuple under investigation.
571572#[ derive( Clone ) ]
572573struct PatStack < ' p , ' tcx > {
573- // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well.
574- pats : SmallVec < [ & ' p DeconstructedPat < ' p , ' tcx > ; 2 ] > ,
574+ pats : & ' p [ & ' p DeconstructedPat < ' p , ' tcx > ] ,
575575}
576576
577577impl < ' p , ' tcx > PatStack < ' p , ' tcx > {
578- fn from_pattern ( pat : & ' p DeconstructedPat < ' p , ' tcx > ) -> Self {
579- PatStack { pats : smallvec ! [ pat] }
578+ fn from_pattern ( cx : & MatchCheckCtxt < ' p , ' _ > , pat : & ' p DeconstructedPat < ' p , ' tcx > ) -> Self {
579+ PatStack { pats : cx . dropless_arena . alloc_from_iter ( once ( pat) ) }
580580 }
581581
582582 fn is_empty ( & self ) -> bool {
@@ -597,11 +597,14 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
597597
598598 // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is
599599 // an or-pattern. Panics if `self` is empty.
600- fn expand_or_pat < ' a > ( & ' a self ) -> impl Iterator < Item = PatStack < ' p , ' tcx > > + Captures < ' a > {
601- self . head ( ) . flatten_or_pat ( ) . into_iter ( ) . map ( move |pat| {
602- let mut new_pats = smallvec ! [ pat] ;
603- new_pats. extend_from_slice ( & self . pats [ 1 ..] ) ;
604- PatStack { pats : new_pats }
600+ fn expand_or_pat < ' a > (
601+ & ' a self ,
602+ cx : & ' a MatchCheckCtxt < ' p , ' tcx > ,
603+ ) -> impl Iterator < Item = PatStack < ' p , ' tcx > > + Captures < ' a > {
604+ self . head ( ) . flatten_or_pat ( ) . into_iter ( ) . map ( move |pat| PatStack {
605+ pats : cx
606+ . dropless_arena
607+ . alloc_from_iter ( once ( pat) . chain ( self . pats [ 1 ..] . iter ( ) . copied ( ) ) ) ,
605608 } )
606609 }
607610
@@ -614,9 +617,13 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
614617 ) -> PatStack < ' p , ' tcx > {
615618 // We pop the head pattern and push the new fields extracted from the arguments of
616619 // `self.head()`.
617- let mut new_pats = self . head ( ) . specialize ( pcx, ctor) ;
618- new_pats. extend_from_slice ( & self . pats [ 1 ..] ) ;
619- PatStack { pats : new_pats }
620+ let ctor_fields = self . head ( ) . specialize ( pcx, ctor) ;
621+ PatStack {
622+ pats : pcx
623+ . cx
624+ . dropless_arena
625+ . alloc_from_iter ( ctor_fields. into_iter ( ) . chain ( self . pats [ 1 ..] . iter ( ) . copied ( ) ) ) ,
626+ }
620627 }
621628}
622629
@@ -667,8 +674,11 @@ impl<'p, 'tcx> MatrixRow<'p, 'tcx> {
667674
668675 // Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is
669676 // 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 {
677+ fn expand_or_pat < ' a > (
678+ & ' a self ,
679+ cx : & ' a MatchCheckCtxt < ' p , ' tcx > ,
680+ ) -> impl Iterator < Item = MatrixRow < ' p , ' tcx > > + Captures < ' a > {
681+ self . pats . expand_or_pat ( cx) . map ( |patstack| MatrixRow {
672682 pats : patstack,
673683 parent_row : self . parent_row ,
674684 is_under_guard : self . is_under_guard ,
@@ -711,7 +721,7 @@ impl<'p, 'tcx> fmt::Debug for MatrixRow<'p, 'tcx> {
711721/// the matrix will correspond to `scrutinee.0.Some.0` and the second column to `scrutinee.1`.
712722#[ derive( Clone ) ]
713723struct Matrix < ' p , ' tcx > {
714- rows : Vec < MatrixRow < ' p , ' tcx > > ,
724+ rows : SmallVec < [ MatrixRow < ' p , ' tcx > ; 8 ] > ,
715725 /// Stores an extra fictitious row full of wildcards. Mostly used to keep track of the type of
716726 /// each column. This must obey the same invariants as the real rows.
717727 wildcard_row : PatStack < ' p , ' tcx > ,
@@ -720,10 +730,10 @@ struct Matrix<'p, 'tcx> {
720730impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
721731 /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
722732 /// expands it. Internal method, prefer [`Matrix::new`].
723- fn expand_and_push ( & mut self , row : MatrixRow < ' p , ' tcx > ) {
733+ fn expand_and_push ( & mut self , cx : & MatchCheckCtxt < ' p , ' tcx > , row : MatrixRow < ' p , ' tcx > ) {
724734 if !row. is_empty ( ) && row. head ( ) . is_or_pat ( ) {
725735 // Expand nested or-patterns.
726- for new_row in row. expand_or_pat ( ) {
736+ for new_row in row. expand_or_pat ( cx ) {
727737 self . rows . push ( new_row) ;
728738 }
729739 } else {
@@ -732,25 +742,18 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
732742 }
733743
734744 /// Build a new matrix from an iterator of `MatchArm`s.
735- fn new < ' a > (
736- cx : & MatchCheckCtxt < ' p , ' tcx > ,
737- iter : impl Iterator < Item = & ' a MatchArm < ' p , ' tcx > > ,
738- scrut_ty : Ty < ' tcx > ,
739- ) -> Self
740- where
741- ' p : ' a ,
742- {
745+ fn new ( cx : & MatchCheckCtxt < ' p , ' tcx > , arms : & [ MatchArm < ' p , ' tcx > ] , scrut_ty : Ty < ' tcx > ) -> Self {
743746 let wild_pattern = cx. pattern_arena . alloc ( DeconstructedPat :: wildcard ( scrut_ty, DUMMY_SP ) ) ;
744- let wildcard_row = PatStack :: from_pattern ( wild_pattern) ;
745- let mut matrix = Matrix { rows : vec ! [ ] , wildcard_row } ;
746- for ( row_id, arm) in iter. enumerate ( ) {
747+ let wildcard_row = PatStack :: from_pattern ( cx , wild_pattern) ;
748+ let mut matrix = Matrix { rows : SmallVec :: with_capacity ( arms . len ( ) ) , wildcard_row } ;
749+ for ( row_id, arm) in arms . iter ( ) . enumerate ( ) {
747750 let v = MatrixRow {
748- pats : PatStack :: from_pattern ( arm. pat ) ,
751+ pats : PatStack :: from_pattern ( cx , arm. pat ) ,
749752 parent_row : row_id, // dummy, we won't read it
750753 is_under_guard : arm. has_guard ,
751754 reachable : false ,
752755 } ;
753- matrix. expand_and_push ( v) ;
756+ matrix. expand_and_push ( cx , v) ;
754757 }
755758 matrix
756759 }
@@ -806,11 +809,12 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
806809 ctor : & Constructor < ' tcx > ,
807810 ) -> Matrix < ' p , ' tcx > {
808811 let wildcard_row = self . wildcard_row . pop_head_constructor ( pcx, ctor) ;
809- let mut matrix = Matrix { rows : vec ! [ ] , wildcard_row } ;
812+ let rows = SmallVec :: with_capacity ( self . rows . len ( ) ) ; // Better waste capacity than reallocate a lot.
813+ let mut matrix = Matrix { rows, wildcard_row } ;
810814 for ( i, row) in self . rows ( ) . enumerate ( ) {
811815 if ctor. is_covered_by ( pcx, row. head ( ) . ctor ( ) ) {
812816 let new_row = row. pop_head_constructor ( pcx, ctor, i) ;
813- matrix. expand_and_push ( new_row) ;
817+ matrix. expand_and_push ( pcx . cx , new_row) ;
814818 }
815819 }
816820 matrix
@@ -1386,7 +1390,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
13861390 arms : & [ MatchArm < ' p , ' tcx > ] ,
13871391 scrut_ty : Ty < ' tcx > ,
13881392) -> UsefulnessReport < ' p , ' tcx > {
1389- let mut matrix = Matrix :: new ( cx, arms. iter ( ) , scrut_ty) ;
1393+ let mut matrix = Matrix :: new ( cx, arms, scrut_ty) ;
13901394 let non_exhaustiveness_witnesses =
13911395 compute_exhaustiveness_and_reachability ( cx, & mut matrix, true ) ;
13921396
0 commit comments