@@ -499,7 +499,7 @@ use crate::errors::{
499
499
500
500
use rustc_data_structures:: captures:: Captures ;
501
501
502
- use rustc_arena:: TypedArena ;
502
+ use rustc_arena:: { DroplessArena , TypedArena } ;
503
503
use rustc_data_structures:: stack:: ensure_sufficient_stack;
504
504
use rustc_hir:: def_id:: DefId ;
505
505
use rustc_hir:: HirId ;
@@ -508,8 +508,8 @@ use rustc_session::lint;
508
508
use rustc_session:: lint:: builtin:: NON_EXHAUSTIVE_OMITTED_PATTERNS ;
509
509
use rustc_span:: { Span , DUMMY_SP } ;
510
510
511
- use smallvec:: { smallvec , SmallVec } ;
512
- use std:: fmt;
511
+ use smallvec:: SmallVec ;
512
+ use std:: { fmt, iter :: once } ;
513
513
514
514
pub ( crate ) struct MatchCheckCtxt < ' p , ' tcx > {
515
515
pub ( crate ) tcx : TyCtxt < ' tcx > ,
@@ -521,6 +521,7 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
521
521
pub ( crate ) module : DefId ,
522
522
pub ( crate ) param_env : ty:: ParamEnv < ' tcx > ,
523
523
pub ( crate ) pattern_arena : & ' p TypedArena < DeconstructedPat < ' p , ' tcx > > ,
524
+ pub ( crate ) dropless_arena : & ' p DroplessArena ,
524
525
/// Lint level at the match.
525
526
pub ( crate ) match_lint_level : HirId ,
526
527
/// The span of the whole match, if applicable.
@@ -570,13 +571,12 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
570
571
/// Represents a pattern-tuple under investigation.
571
572
#[ derive( Clone ) ]
572
573
struct 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 > ] ,
575
575
}
576
576
577
577
impl < ' 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) ) }
580
580
}
581
581
582
582
fn is_empty ( & self ) -> bool {
@@ -597,11 +597,14 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
597
597
598
598
// Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is
599
599
// 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 ( ) ) ) ,
605
608
} )
606
609
}
607
610
@@ -614,9 +617,13 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
614
617
) -> PatStack < ' p , ' tcx > {
615
618
// We pop the head pattern and push the new fields extracted from the arguments of
616
619
// `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
+ }
620
627
}
621
628
}
622
629
@@ -667,8 +674,11 @@ impl<'p, 'tcx> MatrixRow<'p, 'tcx> {
667
674
668
675
// Recursively expand the first or-pattern into its subpatterns. Only useful if the pattern is
669
676
// 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 {
672
682
pats : patstack,
673
683
parent_row : self . parent_row ,
674
684
is_under_guard : self . is_under_guard ,
@@ -711,7 +721,7 @@ impl<'p, 'tcx> fmt::Debug for MatrixRow<'p, 'tcx> {
711
721
/// the matrix will correspond to `scrutinee.0.Some.0` and the second column to `scrutinee.1`.
712
722
#[ derive( Clone ) ]
713
723
struct Matrix < ' p , ' tcx > {
714
- rows : Vec < MatrixRow < ' p , ' tcx > > ,
724
+ rows : SmallVec < [ MatrixRow < ' p , ' tcx > ; 8 ] > ,
715
725
/// Stores an extra fictitious row full of wildcards. Mostly used to keep track of the type of
716
726
/// each column. This must obey the same invariants as the real rows.
717
727
wildcard_row : PatStack < ' p , ' tcx > ,
@@ -720,10 +730,10 @@ struct Matrix<'p, 'tcx> {
720
730
impl < ' p , ' tcx > Matrix < ' p , ' tcx > {
721
731
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
722
732
/// 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 > ) {
724
734
if !row. is_empty ( ) && row. head ( ) . is_or_pat ( ) {
725
735
// Expand nested or-patterns.
726
- for new_row in row. expand_or_pat ( ) {
736
+ for new_row in row. expand_or_pat ( cx ) {
727
737
self . rows . push ( new_row) ;
728
738
}
729
739
} else {
@@ -732,25 +742,18 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
732
742
}
733
743
734
744
/// 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 {
743
746
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 ( ) {
747
750
let v = MatrixRow {
748
- pats : PatStack :: from_pattern ( arm. pat ) ,
751
+ pats : PatStack :: from_pattern ( cx , arm. pat ) ,
749
752
parent_row : row_id, // dummy, we won't read it
750
753
is_under_guard : arm. has_guard ,
751
754
reachable : false ,
752
755
} ;
753
- matrix. expand_and_push ( v) ;
756
+ matrix. expand_and_push ( cx , v) ;
754
757
}
755
758
matrix
756
759
}
@@ -806,11 +809,12 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
806
809
ctor : & Constructor < ' tcx > ,
807
810
) -> Matrix < ' p , ' tcx > {
808
811
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 } ;
810
814
for ( i, row) in self . rows ( ) . enumerate ( ) {
811
815
if ctor. is_covered_by ( pcx, row. head ( ) . ctor ( ) ) {
812
816
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) ;
814
818
}
815
819
}
816
820
matrix
@@ -1386,7 +1390,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
1386
1390
arms : & [ MatchArm < ' p , ' tcx > ] ,
1387
1391
scrut_ty : Ty < ' tcx > ,
1388
1392
) -> UsefulnessReport < ' p , ' tcx > {
1389
- let mut matrix = Matrix :: new ( cx, arms. iter ( ) , scrut_ty) ;
1393
+ let mut matrix = Matrix :: new ( cx, arms, scrut_ty) ;
1390
1394
let non_exhaustiveness_witnesses =
1391
1395
compute_exhaustiveness_and_reachability ( cx, & mut matrix, true ) ;
1392
1396
0 commit comments