@@ -225,6 +225,7 @@ use self::Constructor::*;
225
225
use self :: Usefulness :: * ;
226
226
use self :: WitnessPreference :: * ;
227
227
228
+ use rustc_data_structures:: fx:: FxHashSet ;
228
229
use rustc_index:: vec:: Idx ;
229
230
230
231
use super :: { compare_const_vals, PatternFoldable , PatternFolder } ;
@@ -942,25 +943,22 @@ impl<'tcx> Constructor<'tcx> {
942
943
// [0] => {}
943
944
// [_, _, _] => {}
944
945
// [1, 2, 3, 4, 5, 6, ..] => {}
945
- // [_, _, _, _, _, _, _, _ ] => {}
946
+ // [_, _, _, _, _, _, _] => {}
946
947
// [0, ..] => {}
947
948
// }
948
949
// ```
949
950
// We want to know which constructors are matched by the last pattern, but are not
950
951
// 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.
952
953
// For that, we first notice that because of the third pattern, all constructors of
953
954
// 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)]`.
964
962
965
963
// Initially we cover all slice lengths starting from self_len.
966
964
let self_len = self_prefix + self_suffix;
@@ -975,70 +973,50 @@ impl<'tcx> Constructor<'tcx> {
975
973
} )
976
974
. min ( ) ;
977
975
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
+
978
980
// If max_len <= self_len there are no lengths remaining.
979
981
if let Some ( max_len) = max_len {
980
982
if max_len <= self_len {
981
983
return smallvec ! [ ] ;
982
984
}
983
985
}
984
986
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
999
989
. iter ( )
1000
- // Extract fixed-size lengths
1001
990
. filter_map ( |c : & Constructor < ' tcx > | match c {
1002
- FixedLenSlice ( other_len ) => Some ( * other_len ) ,
991
+ FixedLenSlice ( len ) => Some ( * len ) ,
1003
992
_ => None ,
1004
993
} )
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 )
1027
994
. collect ( ) ;
1028
995
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 ( )
1039
1019
}
1040
-
1041
- remaining_ctors
1042
1020
}
1043
1021
IntRange ( range) => {
1044
1022
let used_ranges = used_ctors. iter ( ) . flat_map ( IntRange :: from_ctor) ;
0 commit comments