@@ -334,15 +334,15 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
334
334
}
335
335
}
336
336
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.
339
338
#[ derive( Debug , Clone ) ]
340
339
pub struct PatStack < ' p , ' tcx > {
340
+ // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well.
341
341
patterns : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ,
342
342
// This caches the invocation of `pat_constructors` on the head of the stack. We avoid mutating
343
343
// `self` to be sure we don't keep an invalid cache around. Must be non-empty unless `patterns`
344
344
// is empty.
345
- head_ctors_cache : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
345
+ head_ctors : SmallVec < [ Constructor < ' tcx > ; 1 ] > ,
346
346
}
347
347
348
348
impl < ' p , ' tcx > PatStack < ' p , ' tcx > {
@@ -351,15 +351,15 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
351
351
}
352
352
353
353
fn empty ( ) -> Self {
354
- PatStack { patterns : smallvec ! [ ] , head_ctors_cache : smallvec ! [ ] }
354
+ PatStack { patterns : smallvec ! [ ] , head_ctors : smallvec ! [ ] }
355
355
}
356
356
357
357
fn from_vec ( cx : & MatchCheckCtxt < ' _ , ' tcx > , patterns : SmallVec < [ & ' p Pat < ' tcx > ; 2 ] > ) -> Self {
358
358
if patterns. is_empty ( ) {
359
359
return PatStack :: empty ( ) ;
360
360
}
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 }
363
363
}
364
364
365
365
fn from_slice ( cx : & MatchCheckCtxt < ' _ , ' tcx > , s : & [ & ' p Pat < ' tcx > ] ) -> Self {
@@ -378,10 +378,8 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
378
378
self . patterns [ 0 ]
379
379
}
380
380
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
385
383
}
386
384
387
385
fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
@@ -436,8 +434,8 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
436
434
self . 0 . iter ( ) . map ( |r| r. head ( ) )
437
435
}
438
436
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 ( )
441
439
}
442
440
443
441
/// This computes `S(constructor, self)`. See top of the file for explanations.
@@ -641,18 +639,18 @@ impl<'tcx> Constructor<'tcx> {
641
639
/// for the given matrix. See description of the algorithm for details.
642
640
/// Note: We can rely on this returning an empty list if the type is (visibly) uninhabited.
643
641
fn split_meta_constructor (
644
- self ,
642
+ & self ,
645
643
cx : & MatchCheckCtxt < ' _ , ' tcx > ,
646
644
ty : Ty < ' tcx > ,
647
- head_ctors : & Vec < Constructor < ' tcx > > ,
645
+ head_ctors : & Vec < & Constructor < ' tcx > > ,
648
646
) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
649
647
debug ! ( "split_meta_constructor {:?}" , self ) ;
650
648
assert ! ( !head_ctors. iter( ) . any( |c| c. is_wildcard( ) ) ) ;
651
649
652
- match self {
650
+ match * self {
653
651
// 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) => {
656
654
// Splitting up a range naïvely would mean creating a separate constructor for
657
655
// every single value in the range, which is clearly impractical. We therefore want
658
656
// to keep together subranges for which the specialisation will be identical across
@@ -708,6 +706,7 @@ impl<'tcx> Constructor<'tcx> {
708
706
// class lies between 2 borders.
709
707
let row_borders = head_ctors
710
708
. iter ( )
709
+ . map ( |c| * c)
711
710
. flat_map ( IntRange :: from_ctor)
712
711
. flat_map ( |range| ctor_range. intersection ( cx. tcx , & range) )
713
712
. flat_map ( |range| range_borders ( range) ) ;
@@ -736,7 +735,7 @@ impl<'tcx> Constructor<'tcx> {
736
735
. collect ( )
737
736
}
738
737
// When not treated exhaustively, don't split ranges.
739
- ConstantRange ( ..) | IntRange ( ..) => smallvec ! [ self ] ,
738
+ ConstantRange ( ..) | IntRange ( ..) => smallvec ! [ self . clone ( ) ] ,
740
739
VarLenSlice ( self_prefix, self_suffix) => {
741
740
// A variable-length slice pattern is matched by an infinite collection of
742
741
// fixed-length array patterns. However it turns out that for each finite set of
@@ -806,7 +805,7 @@ impl<'tcx> Constructor<'tcx> {
806
805
let mut max_fixed_len = 0 ;
807
806
808
807
for ctor in head_ctors {
809
- match * ctor {
808
+ match * * ctor {
810
809
ConstantValue ( value) => {
811
810
// Extract the length of an array/slice from a constant
812
811
match ( value. val , & value. ty . kind ) {
@@ -868,8 +867,12 @@ impl<'tcx> Constructor<'tcx> {
868
867
// Therefore, if there is some pattern that is unmatched by `matrix`,
869
868
// it will still be unmatched if the first constructor is replaced by
870
869
// 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
+ ) ;
873
876
debug ! (
874
877
"missing_ctors.is_empty()={:#?} is_non_exhaustive={:#?}" ,
875
878
missing_ctors. is_empty( ) ,
@@ -1760,7 +1763,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
1760
1763
1761
1764
debug ! ( "is_useful_expand_first_col: ty={:#?}, expanding {:#?}" , ty, v. head( ) ) ;
1762
1765
1763
- let v_constructors = v. head_ctors ( cx ) ;
1766
+ let v_constructors = v. head_ctors ( ) ;
1764
1767
1765
1768
if cx. is_non_exhaustive_variant ( v. head ( ) )
1766
1769
&& !cx. is_local ( ty)
@@ -1771,11 +1774,11 @@ pub fn is_useful<'p, 'a, 'tcx>(
1771
1774
return Useful ;
1772
1775
}
1773
1776
1774
- let matrix_head_ctors = matrix. head_ctors ( cx ) ;
1777
+ let matrix_head_ctors = matrix. head_ctors ( ) ;
1775
1778
debug ! ( "matrix_head_ctors = {:#?}" , matrix_head_ctors) ;
1776
1779
1777
1780
v_constructors
1778
- . into_iter ( )
1781
+ . iter ( )
1779
1782
. flat_map ( |ctor| ctor. split_meta_constructor ( cx, ty, & matrix_head_ctors) )
1780
1783
. map ( |c| is_useful_specialized ( cx, matrix, v, c, ty, witness_preference) )
1781
1784
. find ( |result| result. is_useful ( ) )
0 commit comments