@@ -225,6 +225,7 @@ use self::Constructor::*;
225225use self :: Usefulness :: * ;
226226use self :: WitnessPreference :: * ;
227227
228+ use rustc_data_structures:: fx:: FxHashSet ;
228229use rustc_index:: vec:: Idx ;
229230
230231use super :: { compare_const_vals, PatternFoldable , PatternFolder } ;
@@ -942,25 +943,22 @@ impl<'tcx> Constructor<'tcx> {
942943 // [0] => {}
943944 // [_, _, _] => {}
944945 // [1, 2, 3, 4, 5, 6, ..] => {}
945- // [_, _, _, _, _, _, _, _ ] => {}
946+ // [_, _, _, _, _, _, _] => {}
946947 // [0, ..] => {}
947948 // }
948949 // ```
949950 // We want to know which constructors are matched by the last pattern, but are not
950951 // matched by the first four ones. Since we only speak of constructors here, we
951- // only care about the length of the slices and not the subpatterns.
952+ // only care about the length of the slices and not the particular subpatterns.
952953 // For that, we first notice that because of the third pattern, all constructors of
953954 // lengths 6 or more are covered already. `max_len` will be `Some(6)`.
954- // Then we'll look at constructors of lengths < 6 to see which are missing. We can
955- // ignore pattern 4 because it's longer than 6. We are left with patterns 1 and 2.
956- // The `length` vector will therefore contain `[Start, Boundary(1), Boundary(3),
957- // Boundary(6)]`.
958- // The resulting list of remaining constructors will be those strictly between
959- // those boundaries. Knowing that `self_len` is 1, we get `[FixedLenSlice(2),
960- // FixedLenSlice(4), FixedLenSlice(5)]`.
961- // Notice that `FixedLenSlice(0)` is not covered by any of the patterns here, but
962- // we don't care because we only want constructors that _are_ matched by the last
963- // pattern.
955+ // Then we'll look at fixed-length constructors to see which are missing. The
956+ // returned list of constructors will be those of lengths in 1..6 that are not
957+ // present in the match. Lengths 1, 3 and 7 are matched already, so we get
958+ // `[FixedLenSlice(2), FixedLenSlice(4), FixedLenSlice(5)]`.
959+ // If we had removed the third pattern, we would have instead returned
960+ // `[FixedLenSlice(2), FixedLenSlice(4), FixedLenSlice(5), FixedLenSlice(6),
961+ // VarLenSlice(8, 0)]`.
964962
965963 // Initially we cover all slice lengths starting from self_len.
966964 let self_len = self_prefix + self_suffix;
@@ -975,70 +973,50 @@ impl<'tcx> Constructor<'tcx> {
975973 } )
976974 . min ( ) ;
977975
976+ // The remaining range of lengths is now either `self_len..`
977+ // or `self_len..max_len`. We then remove from that range all the
978+ // individual FixedLenSlice lengths in used_ctors.
979+
978980 // If max_len <= self_len there are no lengths remaining.
979981 if let Some ( max_len) = max_len {
980982 if max_len <= self_len {
981983 return smallvec ! [ ] ;
982984 }
983985 }
984986
985- // The remaining range of lengths is now either `self_len..`
986- // or `self_len..max_len`. We then remove from that range all the
987- // individual FixedLenSlice lengths in used_ctors. For that,
988- // we extract all those lengths that are in our remaining range and
989- // sort them. Every such length becomes a boundary between ranges
990- // of the lengths that will remain.
991- #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
992- enum Length {
993- Start , // `Start` will be sorted before `Boundary`
994- Boundary ( u64 ) ,
995- }
996- use Length :: * ;
997-
998- let mut lengths: Vec < _ > = used_ctors
987+ // Extract fixed-size lengths
988+ let used_fixed_lengths: FxHashSet < u64 > = used_ctors
999989 . iter ( )
1000- // Extract fixed-size lengths
1001990 . filter_map ( |c : & Constructor < ' tcx > | match c {
1002- FixedLenSlice ( other_len ) => Some ( * other_len ) ,
991+ FixedLenSlice ( len ) => Some ( * len ) ,
1003992 _ => None ,
1004993 } )
1005- // Keep only those in the remaining range
1006- . filter ( |l| * l >= self_len)
1007- . filter ( |l| match max_len {
1008- Some ( max_len) => * l < max_len,
1009- None => true ,
1010- } )
1011- . chain ( max_len) // Add max_len as the final boundary
1012- . map ( Boundary )
1013- . chain ( Some ( Start ) ) // Add a special starting boundary
1014- . collect ( ) ;
1015- lengths. sort_unstable ( ) ;
1016- lengths. dedup ( ) ;
1017-
1018- // For each adjacent pair of lengths, output the lengths in between.
1019- let mut remaining_ctors: SmallVec < _ > = lengths
1020- . windows ( 2 )
1021- . flat_map ( |window| match ( window[ 0 ] , window[ 1 ] ) {
1022- ( Boundary ( n) , Boundary ( m) ) => ( n + 1 ..m) ,
1023- ( Start , Boundary ( m) ) => ( self_len..m) ,
1024- _ => bug ! ( ) ,
1025- } )
1026- . map ( FixedLenSlice )
1027994 . collect ( ) ;
1028995
1029- // If there was a max_len, then we're done. Otherwise, we
1030- // still need to include all lengths starting from the longest
1031- // one until infinity, using VarLenSlice.
1032- if max_len. is_none ( ) {
1033- let final_length = match lengths. last ( ) . unwrap ( ) {
1034- Start => self_len,
1035- Boundary ( n) => n + 1 ,
1036- } ;
1037- // We know final_length >= self_len >= self_suffix so this can't underflow.
1038- remaining_ctors. push ( VarLenSlice ( final_length - self_suffix, self_suffix) ) ;
996+ if let Some ( max_len) = max_len {
997+ ( self_len..max_len)
998+ . filter ( |len| !used_fixed_lengths. contains ( len) )
999+ . map ( FixedLenSlice )
1000+ . collect ( )
1001+ } else {
1002+ // Choose a length for which we know that all larger lengths remain in the
1003+ // output.
1004+ let min_free_length = used_fixed_lengths
1005+ . iter ( )
1006+ . map ( |len| len + 1 )
1007+ . chain ( Some ( self_len) )
1008+ . max ( )
1009+ . unwrap ( ) ;
1010+
1011+ // We know min_free_length >= self_len >= self_suffix so this can't underflow.
1012+ let final_varlen = VarLenSlice ( min_free_length - self_suffix, self_suffix) ;
1013+
1014+ ( self_len..min_free_length)
1015+ . filter ( |len| !used_fixed_lengths. contains ( len) )
1016+ . map ( FixedLenSlice )
1017+ . chain ( Some ( final_varlen) )
1018+ . collect ( )
10391019 }
1040-
1041- remaining_ctors
10421020 }
10431021 IntRange ( range) => {
10441022 let used_ranges = used_ctors. iter ( ) . flat_map ( IntRange :: from_ctor) ;
0 commit comments