225225/// anything special (because we know none of the integers are actually wildcards: i.e., we
226226/// can't span wildcards using ranges).
227227use self :: Constructor :: * ;
228+ use self :: SliceKind :: * ;
228229use self :: Usefulness :: * ;
229230use self :: WitnessPreference :: * ;
230231
@@ -582,6 +583,23 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
582583 }
583584}
584585
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+
585603#[ derive( Clone , Debug , PartialEq ) ]
586604enum Constructor < ' tcx > {
587605 /// The constructor of all patterns that don't vary by constructor,
@@ -595,26 +613,20 @@ enum Constructor<'tcx> {
595613 IntRange ( IntRange < ' tcx > ) ,
596614 /// Ranges of floating-point literal values (`2.0..=5.2`).
597615 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 ,
607621 } ,
608- /// Slice patterns. Captures any array constructor of `length >= i + j`.
609- VarLenSlice ( u64 , u64 ) ,
610622 /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
611623 NonExhaustive ,
612624}
613625
614626impl < ' tcx > Constructor < ' tcx > {
615627 fn is_slice ( & self ) -> bool {
616628 match self {
617- FixedLenSlice { .. } | LazyFixedLenSlice { .. } | VarLenSlice { .. } => true ,
629+ Slice { .. } => true ,
618630 _ => false ,
619631 }
620632 }
@@ -643,71 +655,89 @@ impl<'tcx> Constructor<'tcx> {
643655 Single | Variant ( _) | ConstantValue ( ..) | FloatRange ( ..) => {
644656 if other_ctors. iter ( ) . any ( |c| c == self ) { vec ! [ ] } else { vec ! [ self . clone( ) ] }
645657 }
646- & FixedLenSlice ( self_len) | & LazyFixedLenSlice { len : self_len, .. } => {
658+ & Slice { type_len : Some ( self_len) , .. } | & Slice { kind : FixedLen ( self_len) , .. } => {
647659 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+ }
650666 _ => false ,
651667 } ;
652668 if other_ctors. iter ( ) . any ( overlaps) { vec ! [ ] } else { vec ! [ self . clone( ) ] }
653669 }
654- VarLenSlice ( ..) => {
670+ Slice { type_len : None , kind : VarLen ( ..) } => {
655671 let mut remaining_ctors = vec ! [ self . clone( ) ] ;
656672
657673 // For each used ctor, subtract from the current set of constructors.
658674 // 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
660676 // `i + j` to infinity.
661677 for neg_ctor in other_ctors {
662678 remaining_ctors = remaining_ctors
663679 . into_iter ( )
664680 . flat_map ( |pos_ctor| -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
665681 // Compute `pos_ctor \ neg_ctor`.
666682 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) , .. }
670687 if neg_len == pos_len =>
671688 {
672689 smallvec ! [ ]
673690 }
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 ! [ ] ,
679695 _ => smallvec ! [ pos_ctor] ,
680696 } ,
681- VarLenSlice ( pos_prefix, pos_suffix) => {
697+ Slice { type_len : None , kind : VarLen ( pos_prefix, pos_suffix) } => {
682698 let pos_len = pos_prefix + pos_suffix;
683699 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) , .. }
686702 if neg_len >= pos_len =>
687703 {
688704 ( pos_len..neg_len)
689- . map ( FixedLenSlice )
705+ . map ( |l| Slice {
706+ type_len : None ,
707+ kind : FixedLen ( l) ,
708+ } )
690709 // We know that `neg_len + 1 >= pos_len >=
691710 // 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+ } ) )
696718 . collect ( )
697719 }
698- VarLenSlice ( neg_prefix, neg_suffix) => {
720+ Slice {
721+ type_len : None ,
722+ kind : VarLen ( neg_prefix, neg_suffix) ,
723+ } => {
699724 let neg_len = neg_prefix + neg_suffix;
700725 if neg_len <= pos_len {
701726 smallvec ! [ ]
702727 } 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 ( )
704734 }
705735 }
706736 _ => smallvec ! [ pos_ctor] ,
707737 }
708738 }
709739 _ => bug ! (
710- "unexpected ctor while subtracting from VarLenSlice : {:?}" ,
740+ "unexpected ctor while subtracting from VarLen : {:?}" ,
711741 pos_ctor
712742 ) ,
713743 }
@@ -815,7 +845,7 @@ impl<'tcx> Constructor<'tcx> {
815845 }
816846 _ => vec ! [ ] ,
817847 } ,
818- FixedLenSlice ( _ ) | LazyFixedLenSlice { .. } | VarLenSlice ( .. ) => match ty. kind {
848+ Slice { .. } => match ty. kind {
819849 ty:: Slice ( ty) | ty:: Array ( ty, _) => {
820850 let arity = self . arity ( cx, ty) ;
821851 ( 0 ..arity) . map ( |_| Pat :: wildcard_from_ty ( ty) ) . collect ( )
@@ -845,10 +875,7 @@ impl<'tcx> Constructor<'tcx> {
845875 }
846876 _ => 0 ,
847877 } ,
848- FixedLenSlice ( length) => * length,
849- VarLenSlice ( prefix, suffix) | LazyFixedLenSlice { prefix, suffix, .. } => {
850- prefix + suffix
851- }
878+ Slice { kind, .. } => kind. arity ( ) ,
852879 ConstantValue ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive => 0 ,
853880 }
854881 }
@@ -903,13 +930,15 @@ impl<'tcx> Constructor<'tcx> {
903930 ty:: Slice ( _) | ty:: Array ( ..) => bug ! ( "bad slice pattern {:?} {:?}" , self , ty) ,
904931 _ => PatKind :: Wild ,
905932 } ,
906- FixedLenSlice ( _) => {
933+ Slice { kind : FixedLen ( _) , .. } => {
907934 PatKind :: Slice { prefix : subpatterns. collect ( ) , slice : None , suffix : vec ! [ ] }
908935 }
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+ {
910939 PatKind :: Slice { prefix : subpatterns. collect ( ) , slice : None , suffix : vec ! [ ] }
911940 }
912- VarLenSlice ( prefix, _) | LazyFixedLenSlice { prefix , .. } => {
941+ Slice { kind : VarLen ( prefix, _) , .. } => {
913942 let prefix = subpatterns. by_ref ( ) . take ( * prefix as usize ) . collect ( ) ;
914943 let suffix = subpatterns. collect ( ) ;
915944 let wild = Pat :: wildcard_from_ty ( ty) ;
@@ -1130,15 +1159,15 @@ fn all_constructors<'a, 'tcx>(
11301159 if len != 0 && cx. is_uninhabited ( sub_ty) {
11311160 vec ! [ ]
11321161 } else {
1133- vec ! [ LazyFixedLenSlice { len, prefix : 0 , suffix : 0 } ]
1162+ vec ! [ Slice { type_len : Some ( len) , kind : VarLen ( 0 , 0 ) } ]
11341163 }
11351164 }
11361165 // Treat arrays of a constant but unknown length like slices.
11371166 ty:: Array ( ref sub_ty, _) | ty:: Slice ( ref sub_ty) => {
11381167 if cx. is_uninhabited ( sub_ty) {
1139- vec ! [ FixedLenSlice ( 0 ) ]
1168+ vec ! [ Slice { type_len : None , kind : FixedLen ( 0 ) } ]
11401169 } else {
1141- vec ! [ VarLenSlice ( 0 , 0 ) ]
1170+ vec ! [ Slice { type_len : None , kind : VarLen ( 0 , 0 ) } ]
11421171 }
11431172 }
11441173 ty:: Adt ( def, substs) if def. is_enum ( ) => {
@@ -1719,27 +1748,18 @@ fn pat_constructor<'tcx>(
17191748 Some ( FloatRange ( lo, hi, end) )
17201749 }
17211750 }
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) ,
17261757 } ;
17271758 let prefix = prefix. len ( ) as u64 ;
17281759 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 } )
17431763 }
17441764 PatKind :: Or { .. } => {
17451765 bug ! ( "support for or-patterns has not been fully implemented yet." ) ;
@@ -1955,8 +1975,7 @@ fn split_grouped_constructors<'p, 'tcx>(
19551975 . map ( IntRange ) ,
19561976 ) ;
19571977 }
1958- VarLenSlice ( self_prefix, self_suffix)
1959- | LazyFixedLenSlice { prefix : self_prefix, suffix : self_suffix, .. } => {
1978+ Slice { kind : VarLen ( self_prefix, self_suffix) , type_len } => {
19601979 // The exhaustiveness-checking paper does not include any details on
19611980 // checking variable-length slice patterns. However, they are matched
19621981 // by an infinite collection of fixed-length array patterns.
@@ -2065,28 +2084,26 @@ fn split_grouped_constructors<'p, 'tcx>(
20652084 max_prefix_len = max_fixed_len + 1 - max_suffix_len;
20662085 }
20672086
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)
20762091 } else {
2077- split_ctors. push ( FixedLenSlice ( len) ) ;
2078- }
2092+ FixedLen ( len)
2093+ } ;
2094+ split_ctors. push ( Slice { type_len, kind } ) ;
20792095 }
2080- _ => {
2096+ None => {
20812097 // `ctor` originally covered the range `(self_prefix + self_suffix..infinity)`. We
20822098 // now split it into two: lengths smaller than `max_prefix_len + max_suffix_len`
20832099 // 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.
20852101 split_ctors. extend (
20862102 ( self_prefix + self_suffix..max_prefix_len + max_suffix_len)
2087- . map ( FixedLenSlice ) ,
2103+ . map ( |len| Slice { type_len , kind : FixedLen ( len ) } ) ,
20882104 ) ;
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) } ) ;
20902107 }
20912108 }
20922109 }
@@ -2307,7 +2324,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
23072324
23082325 PatKind :: Array { ref prefix, ref slice, ref suffix }
23092326 | PatKind :: Slice { ref prefix, ref slice, ref suffix } => match * constructor {
2310- FixedLenSlice ( .. ) | LazyFixedLenSlice { .. } | VarLenSlice ( .. ) => {
2327+ Slice { .. } => {
23112328 let pat_len = prefix. len ( ) + suffix. len ( ) ;
23122329 if let Some ( slice_count) = ctor_wild_subpatterns. len ( ) . checked_sub ( pat_len) {
23132330 if slice_count == 0 || slice. is_some ( ) {
0 commit comments