@@ -334,15 +334,15 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
334334 }
335335}
336336
337- /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
338- /// works well.
337+ /// A row of a matrix.
339338#[ derive( Debug , Clone ) ]
340339pub struct PatStack < ' p , ' tcx > {
340+ // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well.
341341 patterns : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ,
342342 // This caches the invocation of `pat_constructors` on the head of the stack. We avoid mutating
343343 // `self` to be sure we don't keep an invalid cache around. Must be non-empty unless `patterns`
344344 // is empty.
345- head_ctors_cache : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
345+ head_ctors : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
346346}
347347
348348impl < ' p , ' tcx > PatStack < ' p , ' tcx > {
@@ -351,15 +351,15 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
351351 }
352352
353353 fn empty ( ) -> Self {
354- PatStack { patterns : smallvec ! [ ] , head_ctors_cache : smallvec ! [ ] }
354+ PatStack { patterns : smallvec ! [ ] , head_ctors : smallvec ! [ ] }
355355 }
356356
357357 fn from_vec ( cx : & MatchCheckCtxt < ' _ , ' tcx > , patterns : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) -> Self {
358358 if patterns. is_empty ( ) {
359359 return PatStack :: empty ( ) ;
360360 }
361- let head_ctors_cache = pat_constructors ( cx. tcx , cx. param_env , patterns[ 0 ] ) ;
362- PatStack { patterns, head_ctors_cache }
361+ let head_ctors = pat_constructors ( cx. tcx , cx. param_env , patterns[ 0 ] ) ;
362+ PatStack { patterns, head_ctors }
363363 }
364364
365365 fn from_slice ( cx : & MatchCheckCtxt < ' _ , ' tcx > , s : & [ & ' p Pat < ' tcx > ] ) -> Self {
@@ -378,10 +378,8 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
378378 self . patterns [ 0 ]
379379 }
380380
381- fn head_ctors ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
382- let new_ctors = pat_constructors ( cx. tcx , cx. param_env , self . head ( ) ) ;
383- assert_eq ! ( self . head_ctors_cache, new_ctors) ;
384- new_ctors
381+ fn head_ctors ( & self ) -> & SmallVec < [ Constructor < ' tcx > ; 1 ] > {
382+ & self . head_ctors
385383 }
386384
387385 fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
@@ -436,8 +434,8 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
436434 self . 0 . iter ( ) . map ( |r| r. head ( ) )
437435 }
438436
439- fn head_ctors ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> Vec < Constructor < ' tcx > > {
440- self . 0 . iter ( ) . flat_map ( |r| r. head_ctors ( cx ) ) . filter ( |ctor| !ctor. is_wildcard ( ) ) . collect ( )
437+ fn head_ctors ( & self ) -> Vec < & Constructor < ' tcx > > {
438+ self . 0 . iter ( ) . flat_map ( |r| r. head_ctors ( ) ) . filter ( |ctor| !ctor. is_wildcard ( ) ) . collect ( )
441439 }
442440
443441 /// This computes `S(constructor, self)`. See top of the file for explanations.
@@ -641,18 +639,18 @@ impl<'tcx> Constructor<'tcx> {
641639 /// for the given matrix. See description of the algorithm for details.
642640 /// Note: We can rely on this returning an empty list if the type is (visibly) uninhabited.
643641 fn split_meta_constructor (
644- self ,
642+ & self ,
645643 cx : & MatchCheckCtxt < ' _ , ' tcx > ,
646644 ty : Ty < ' tcx > ,
647- head_ctors : & Vec < Constructor < ' tcx > > ,
645+ head_ctors : & Vec < & Constructor < ' tcx > > ,
648646 ) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
649647 debug ! ( "split_meta_constructor {:?}" , self ) ;
650648 assert ! ( !head_ctors. iter( ) . any( |c| c. is_wildcard( ) ) ) ;
651649
652- match self {
650+ match * self {
653651 // Any base constructor can be used unchanged.
654- Single | Variant ( _) | ConstantValue ( _) | FixedLenSlice ( _) => smallvec ! [ self ] ,
655- IntRange ( ctor_range) if IntRange :: should_treat_range_exhaustively ( cx. tcx , ty) => {
652+ Single | Variant ( _) | ConstantValue ( _) | FixedLenSlice ( _) => smallvec ! [ self . clone ( ) ] ,
653+ IntRange ( ref ctor_range) if IntRange :: should_treat_range_exhaustively ( cx. tcx , ty) => {
656654 // Splitting up a range naïvely would mean creating a separate constructor for
657655 // every single value in the range, which is clearly impractical. We therefore want
658656 // to keep together subranges for which the specialisation will be identical across
@@ -708,6 +706,7 @@ impl<'tcx> Constructor<'tcx> {
708706 // class lies between 2 borders.
709707 let row_borders = head_ctors
710708 . iter ( )
709+ . map ( |c| * c)
711710 . flat_map ( IntRange :: from_ctor)
712711 . flat_map ( |range| ctor_range. intersection ( cx. tcx , & range) )
713712 . flat_map ( |range| range_borders ( range) ) ;
@@ -736,7 +735,7 @@ impl<'tcx> Constructor<'tcx> {
736735 . collect ( )
737736 }
738737 // When not treated exhaustively, don't split ranges.
739- ConstantRange ( ..) | IntRange ( ..) => smallvec ! [ self ] ,
738+ ConstantRange ( ..) | IntRange ( ..) => smallvec ! [ self . clone ( ) ] ,
740739 VarLenSlice ( self_prefix, self_suffix) => {
741740 // A variable-length slice pattern is matched by an infinite collection of
742741 // fixed-length array patterns. However it turns out that for each finite set of
@@ -806,7 +805,7 @@ impl<'tcx> Constructor<'tcx> {
806805 let mut max_fixed_len = 0 ;
807806
808807 for ctor in head_ctors {
809- match * ctor {
808+ match * * ctor {
810809 ConstantValue ( value) => {
811810 // Extract the length of an array/slice from a constant
812811 match ( value. val , & value. ty . kind ) {
@@ -868,8 +867,12 @@ impl<'tcx> Constructor<'tcx> {
868867 // Therefore, if there is some pattern that is unmatched by `matrix`,
869868 // it will still be unmatched if the first constructor is replaced by
870869 // any of the constructors in `missing_ctors`
871- let missing_ctors =
872- MissingConstructors :: new ( cx. tcx , cx. param_env , all_ctors, head_ctors. clone ( ) ) ;
870+ let missing_ctors = MissingConstructors :: new (
871+ cx. tcx ,
872+ cx. param_env ,
873+ all_ctors,
874+ head_ctors. iter ( ) . map ( |c| ( * * c) . clone ( ) ) . collect ( ) ,
875+ ) ;
873876 debug ! (
874877 "missing_ctors.is_empty()={:#?} is_non_exhaustive={:#?}" ,
875878 missing_ctors. is_empty( ) ,
@@ -1760,7 +1763,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
17601763
17611764 debug ! ( "is_useful_expand_first_col: ty={:#?}, expanding {:#?}" , ty, v. head( ) ) ;
17621765
1763- let v_constructors = v. head_ctors ( cx ) ;
1766+ let v_constructors = v. head_ctors ( ) ;
17641767
17651768 if cx. is_non_exhaustive_variant ( v. head ( ) )
17661769 && !cx. is_local ( ty)
@@ -1771,11 +1774,11 @@ pub fn is_useful<'p, 'a, 'tcx>(
17711774 return Useful ;
17721775 }
17731776
1774- let matrix_head_ctors = matrix. head_ctors ( cx ) ;
1777+ let matrix_head_ctors = matrix. head_ctors ( ) ;
17751778 debug ! ( "matrix_head_ctors = {:#?}" , matrix_head_ctors) ;
17761779
17771780 v_constructors
1778- . into_iter ( )
1781+ . iter ( )
17791782 . flat_map ( |ctor| ctor. split_meta_constructor ( cx, ty, & matrix_head_ctors) )
17801783 . map ( |c| is_useful_specialized ( cx, matrix, v, c, ty, witness_preference) )
17811784 . find ( |result| result. is_useful ( ) )
0 commit comments