225
225
/// anything special (because we know none of the integers are actually wildcards: i.e., we
226
226
/// can't span wildcards using ranges).
227
227
use self :: Constructor :: * ;
228
+ use self :: SliceKind :: * ;
228
229
use self :: Usefulness :: * ;
229
230
use self :: WitnessPreference :: * ;
230
231
@@ -582,6 +583,23 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
582
583
}
583
584
}
584
585
586
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
587
+ enum SliceKind {
588
+ /// Array patterns of length `n`.
589
+ FixedLen ( u64 ) ,
590
+ /// Slice patterns. Captures any array constructor of `length >= i + j`.
591
+ VarLen ( u64 , u64 ) ,
592
+ }
593
+
594
+ impl SliceKind {
595
+ fn arity ( self ) -> u64 {
596
+ match self {
597
+ FixedLen ( length) => length,
598
+ VarLen ( prefix, suffix) => prefix + suffix,
599
+ }
600
+ }
601
+ }
602
+
585
603
#[ derive( Clone , Debug , PartialEq ) ]
586
604
enum Constructor < ' tcx > {
587
605
/// The constructor of all patterns that don't vary by constructor,
@@ -595,26 +613,20 @@ enum Constructor<'tcx> {
595
613
IntRange ( IntRange < ' tcx > ) ,
596
614
/// Ranges of floating-point literal values (`2.0..=5.2`).
597
615
FloatRange ( & ' tcx ty:: Const < ' tcx > , & ' tcx ty:: Const < ' tcx > , RangeEnd ) ,
598
- /// Array patterns of length `n`.
599
- FixedLenSlice ( u64 ) ,
600
- /// Array patterns of length `len`, but for which we only care about the `prefix` first values
601
- /// and the `suffix` last values. This avoids unnecessarily going through values we know to be
602
- /// uninteresting, which can be a major problem for large arrays.
603
- LazyFixedLenSlice {
604
- len : u64 , // The actual length of the array
605
- prefix : u64 ,
606
- suffix : u64 ,
616
+ /// Array and slice patterns.
617
+ Slice {
618
+ // The length of the type of the pattern, if fixed.
619
+ type_len : Option < u64 > ,
620
+ kind : SliceKind ,
607
621
} ,
608
- /// Slice patterns. Captures any array constructor of `length >= i + j`.
609
- VarLenSlice ( u64 , u64 ) ,
610
622
/// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
611
623
NonExhaustive ,
612
624
}
613
625
614
626
impl < ' tcx > Constructor < ' tcx > {
615
627
fn is_slice ( & self ) -> bool {
616
628
match self {
617
- FixedLenSlice { .. } | LazyFixedLenSlice { .. } | VarLenSlice { .. } => true ,
629
+ Slice { .. } => true ,
618
630
_ => false ,
619
631
}
620
632
}
@@ -643,71 +655,89 @@ impl<'tcx> Constructor<'tcx> {
643
655
Single | Variant ( _) | ConstantValue ( ..) | FloatRange ( ..) => {
644
656
if other_ctors. iter ( ) . any ( |c| c == self ) { vec ! [ ] } else { vec ! [ self . clone( ) ] }
645
657
}
646
- & FixedLenSlice ( self_len) | & LazyFixedLenSlice { len : self_len, .. } => {
658
+ & Slice { type_len : Some ( self_len) , .. } | & Slice { kind : FixedLen ( self_len) , .. } => {
647
659
let overlaps = |c : & Constructor < ' _ > | match * c {
648
- FixedLenSlice ( len) | LazyFixedLenSlice { len, .. } => len == self_len,
649
- VarLenSlice ( prefix, suffix) => prefix + suffix <= self_len,
660
+ Slice { type_len : Some ( len) , .. } | Slice { kind : FixedLen ( len) , .. } => {
661
+ len == self_len
662
+ }
663
+ Slice { type_len : None , kind : VarLen ( prefix, suffix) } => {
664
+ prefix + suffix <= self_len
665
+ }
650
666
_ => false ,
651
667
} ;
652
668
if other_ctors. iter ( ) . any ( overlaps) { vec ! [ ] } else { vec ! [ self . clone( ) ] }
653
669
}
654
- VarLenSlice ( ..) => {
670
+ Slice { type_len : None , kind : VarLen ( ..) } => {
655
671
let mut remaining_ctors = vec ! [ self . clone( ) ] ;
656
672
657
673
// For each used ctor, subtract from the current set of constructors.
658
674
// Naming: we remove the "neg" constructors from the "pos" ones.
659
- // Remember, `VarLenSlice (i, j)` covers the union of `FixedLenSlice ` from
675
+ // Remember, `VarLen (i, j)` covers the union of `FixedLen ` from
660
676
// `i + j` to infinity.
661
677
for neg_ctor in other_ctors {
662
678
remaining_ctors = remaining_ctors
663
679
. into_iter ( )
664
680
. flat_map ( |pos_ctor| -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
665
681
// Compute `pos_ctor \ neg_ctor`.
666
682
match pos_ctor {
667
- FixedLenSlice ( pos_len) => match * neg_ctor {
668
- FixedLenSlice ( neg_len)
669
- | LazyFixedLenSlice { len : neg_len, .. }
683
+ Slice { type_len : Some ( pos_len) , .. }
684
+ | Slice { kind : FixedLen ( pos_len) , .. } => match * neg_ctor {
685
+ Slice { type_len : Some ( neg_len) , .. }
686
+ | Slice { kind : FixedLen ( neg_len) , .. }
670
687
if neg_len == pos_len =>
671
688
{
672
689
smallvec ! [ ]
673
690
}
674
- VarLenSlice ( neg_prefix, neg_suffix)
675
- if neg_prefix + neg_suffix <= pos_len =>
676
- {
677
- smallvec ! [ ]
678
- }
691
+ Slice {
692
+ type_len : None ,
693
+ kind : VarLen ( neg_prefix, neg_suffix) ,
694
+ } if neg_prefix + neg_suffix <= pos_len => smallvec ! [ ] ,
679
695
_ => smallvec ! [ pos_ctor] ,
680
696
} ,
681
- VarLenSlice ( pos_prefix, pos_suffix) => {
697
+ Slice { type_len : None , kind : VarLen ( pos_prefix, pos_suffix) } => {
682
698
let pos_len = pos_prefix + pos_suffix;
683
699
match * neg_ctor {
684
- FixedLenSlice ( neg_len)
685
- | LazyFixedLenSlice { len : neg_len, .. }
700
+ Slice { type_len : Some ( neg_len) , .. }
701
+ | Slice { kind : FixedLen ( neg_len) , .. }
686
702
if neg_len >= pos_len =>
687
703
{
688
704
( pos_len..neg_len)
689
- . map ( FixedLenSlice )
705
+ . map ( |l| Slice {
706
+ type_len : None ,
707
+ kind : FixedLen ( l) ,
708
+ } )
690
709
// We know that `neg_len + 1 >= pos_len >=
691
710
// pos_suffix`.
692
- . chain ( Some ( VarLenSlice (
693
- neg_len + 1 - pos_suffix,
694
- pos_suffix,
695
- ) ) )
711
+ . chain ( Some ( Slice {
712
+ type_len : None ,
713
+ kind : VarLen (
714
+ neg_len + 1 - pos_suffix,
715
+ pos_suffix,
716
+ ) ,
717
+ } ) )
696
718
. collect ( )
697
719
}
698
- VarLenSlice ( neg_prefix, neg_suffix) => {
720
+ Slice {
721
+ type_len : None ,
722
+ kind : VarLen ( neg_prefix, neg_suffix) ,
723
+ } => {
699
724
let neg_len = neg_prefix + neg_suffix;
700
725
if neg_len <= pos_len {
701
726
smallvec ! [ ]
702
727
} else {
703
- ( pos_len..neg_len) . map ( FixedLenSlice ) . collect ( )
728
+ ( pos_len..neg_len)
729
+ . map ( |l| Slice {
730
+ type_len : None ,
731
+ kind : FixedLen ( l) ,
732
+ } )
733
+ . collect ( )
704
734
}
705
735
}
706
736
_ => smallvec ! [ pos_ctor] ,
707
737
}
708
738
}
709
739
_ => bug ! (
710
- "unexpected ctor while subtracting from VarLenSlice : {:?}" ,
740
+ "unexpected ctor while subtracting from VarLen : {:?}" ,
711
741
pos_ctor
712
742
) ,
713
743
}
@@ -815,7 +845,7 @@ impl<'tcx> Constructor<'tcx> {
815
845
}
816
846
_ => vec ! [ ] ,
817
847
} ,
818
- FixedLenSlice ( _ ) | LazyFixedLenSlice { .. } | VarLenSlice ( .. ) => match ty. kind {
848
+ Slice { .. } => match ty. kind {
819
849
ty:: Slice ( ty) | ty:: Array ( ty, _) => {
820
850
let arity = self . arity ( cx, ty) ;
821
851
( 0 ..arity) . map ( |_| Pat :: wildcard_from_ty ( ty) ) . collect ( )
@@ -845,10 +875,7 @@ impl<'tcx> Constructor<'tcx> {
845
875
}
846
876
_ => 0 ,
847
877
} ,
848
- FixedLenSlice ( length) => * length,
849
- VarLenSlice ( prefix, suffix) | LazyFixedLenSlice { prefix, suffix, .. } => {
850
- prefix + suffix
851
- }
878
+ Slice { kind, .. } => kind. arity ( ) ,
852
879
ConstantValue ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive => 0 ,
853
880
}
854
881
}
@@ -903,13 +930,15 @@ impl<'tcx> Constructor<'tcx> {
903
930
ty:: Slice ( _) | ty:: Array ( ..) => bug ! ( "bad slice pattern {:?} {:?}" , self , ty) ,
904
931
_ => PatKind :: Wild ,
905
932
} ,
906
- FixedLenSlice ( _) => {
933
+ Slice { kind : FixedLen ( _) , .. } => {
907
934
PatKind :: Slice { prefix : subpatterns. collect ( ) , slice : None , suffix : vec ! [ ] }
908
935
}
909
- LazyFixedLenSlice { len, prefix, suffix } if prefix + suffix == * len => {
936
+ Slice { type_len : Some ( len) , kind : VarLen ( prefix, suffix) }
937
+ if prefix + suffix == * len =>
938
+ {
910
939
PatKind :: Slice { prefix : subpatterns. collect ( ) , slice : None , suffix : vec ! [ ] }
911
940
}
912
- VarLenSlice ( prefix, _) | LazyFixedLenSlice { prefix , .. } => {
941
+ Slice { kind : VarLen ( prefix, _) , .. } => {
913
942
let prefix = subpatterns. by_ref ( ) . take ( * prefix as usize ) . collect ( ) ;
914
943
let suffix = subpatterns. collect ( ) ;
915
944
let wild = Pat :: wildcard_from_ty ( ty) ;
@@ -1130,15 +1159,15 @@ fn all_constructors<'a, 'tcx>(
1130
1159
if len != 0 && cx. is_uninhabited ( sub_ty) {
1131
1160
vec ! [ ]
1132
1161
} else {
1133
- vec ! [ LazyFixedLenSlice { len, prefix : 0 , suffix : 0 } ]
1162
+ vec ! [ Slice { type_len : Some ( len) , kind : VarLen ( 0 , 0 ) } ]
1134
1163
}
1135
1164
}
1136
1165
// Treat arrays of a constant but unknown length like slices.
1137
1166
ty:: Array ( ref sub_ty, _) | ty:: Slice ( ref sub_ty) => {
1138
1167
if cx. is_uninhabited ( sub_ty) {
1139
- vec ! [ FixedLenSlice ( 0 ) ]
1168
+ vec ! [ Slice { type_len : None , kind : FixedLen ( 0 ) } ]
1140
1169
} else {
1141
- vec ! [ VarLenSlice ( 0 , 0 ) ]
1170
+ vec ! [ Slice { type_len : None , kind : VarLen ( 0 , 0 ) } ]
1142
1171
}
1143
1172
}
1144
1173
ty:: Adt ( def, substs) if def. is_enum ( ) => {
@@ -1719,27 +1748,18 @@ fn pat_constructor<'tcx>(
1719
1748
Some ( FloatRange ( lo, hi, end) )
1720
1749
}
1721
1750
}
1722
- PatKind :: Array { ref prefix, ref slice, ref suffix } => {
1723
- let len = match pat. ty . kind {
1724
- ty:: Array ( _, length) => length. eval_usize ( tcx, param_env) ,
1725
- _ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , pat. ty) ,
1751
+ PatKind :: Array { ref prefix, ref slice, ref suffix }
1752
+ | PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
1753
+ let type_len = match pat. ty . kind {
1754
+ ty:: Array ( _, length) => Some ( length. eval_usize ( tcx, param_env) ) ,
1755
+ ty:: Slice ( _) => None ,
1756
+ _ => span_bug ! ( pat. span, "bad ty {:?} for slice pattern" , pat. ty) ,
1726
1757
} ;
1727
1758
let prefix = prefix. len ( ) as u64 ;
1728
1759
let suffix = suffix. len ( ) as u64 ;
1729
- if slice. is_some ( ) {
1730
- Some ( LazyFixedLenSlice { len, prefix, suffix } )
1731
- } else {
1732
- Some ( FixedLenSlice ( len) )
1733
- }
1734
- }
1735
- PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
1736
- let prefix = prefix. len ( ) as u64 ;
1737
- let suffix = suffix. len ( ) as u64 ;
1738
- if slice. is_some ( ) {
1739
- Some ( VarLenSlice ( prefix, suffix) )
1740
- } else {
1741
- Some ( FixedLenSlice ( prefix + suffix) )
1742
- }
1760
+ let kind =
1761
+ if slice. is_some ( ) { VarLen ( prefix, suffix) } else { FixedLen ( prefix + suffix) } ;
1762
+ Some ( Slice { type_len, kind } )
1743
1763
}
1744
1764
PatKind :: Or { .. } => {
1745
1765
bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
@@ -1955,8 +1975,7 @@ fn split_grouped_constructors<'p, 'tcx>(
1955
1975
. map ( IntRange ) ,
1956
1976
) ;
1957
1977
}
1958
- VarLenSlice ( self_prefix, self_suffix)
1959
- | LazyFixedLenSlice { prefix : self_prefix, suffix : self_suffix, .. } => {
1978
+ Slice { kind : VarLen ( self_prefix, self_suffix) , type_len } => {
1960
1979
// The exhaustiveness-checking paper does not include any details on
1961
1980
// checking variable-length slice patterns. However, they are matched
1962
1981
// by an infinite collection of fixed-length array patterns.
@@ -2065,28 +2084,26 @@ fn split_grouped_constructors<'p, 'tcx>(
2065
2084
max_prefix_len = max_fixed_len + 1 - max_suffix_len;
2066
2085
}
2067
2086
2068
- match ctor {
2069
- LazyFixedLenSlice { len, .. } => {
2070
- if max_prefix_len + max_suffix_len < len {
2071
- split_ctors. push ( LazyFixedLenSlice {
2072
- len,
2073
- prefix : max_prefix_len,
2074
- suffix : max_suffix_len,
2075
- } ) ;
2087
+ match type_len {
2088
+ Some ( len) => {
2089
+ let kind = if max_prefix_len + max_suffix_len < len {
2090
+ VarLen ( max_prefix_len, max_suffix_len)
2076
2091
} else {
2077
- split_ctors. push ( FixedLenSlice ( len) ) ;
2078
- }
2092
+ FixedLen ( len)
2093
+ } ;
2094
+ split_ctors. push ( Slice { type_len, kind } ) ;
2079
2095
}
2080
- _ => {
2096
+ None => {
2081
2097
// `ctor` originally covered the range `(self_prefix + self_suffix..infinity)`. We
2082
2098
// now split it into two: lengths smaller than `max_prefix_len + max_suffix_len`
2083
2099
// are treated independently as fixed-lengths slices, and lengths above are
2084
- // captured by a final VarLenSlice constructor.
2100
+ // captured by a final VarLen constructor.
2085
2101
split_ctors. extend (
2086
2102
( self_prefix + self_suffix..max_prefix_len + max_suffix_len)
2087
- . map ( FixedLenSlice ) ,
2103
+ . map ( |len| Slice { type_len , kind : FixedLen ( len ) } ) ,
2088
2104
) ;
2089
- split_ctors. push ( VarLenSlice ( max_prefix_len, max_suffix_len) ) ;
2105
+ split_ctors
2106
+ . push ( Slice { type_len, kind : VarLen ( max_prefix_len, max_suffix_len) } ) ;
2090
2107
}
2091
2108
}
2092
2109
}
@@ -2307,7 +2324,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2307
2324
2308
2325
PatKind :: Array { ref prefix, ref slice, ref suffix }
2309
2326
| PatKind :: Slice { ref prefix, ref slice, ref suffix } => match * constructor {
2310
- FixedLenSlice ( .. ) | LazyFixedLenSlice { .. } | VarLenSlice ( .. ) => {
2327
+ Slice { .. } => {
2311
2328
let pat_len = prefix. len ( ) + suffix. len ( ) ;
2312
2329
if let Some ( slice_count) = ctor_wild_subpatterns. len ( ) . checked_sub ( pat_len) {
2313
2330
if slice_count == 0 || slice. is_some ( ) {
0 commit comments