@@ -586,8 +586,7 @@ enum Constructor<'tcx> {
586
586
ConstantValue ( & ' tcx ty:: Const < ' tcx > , Span ) ,
587
587
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
588
588
IntRange ( IntRange < ' tcx > ) ,
589
- // TODO: non-integer
590
- /// Ranges of literal values (`2.0..=5.2`).
589
+ /// Ranges of non-integer literal values (`2.0..=5.2`).
591
590
ConstantRange ( u128 , u128 , Ty < ' tcx > , RangeEnd , Span ) ,
592
591
/// Array patterns of length `n`.
593
592
FixedLenSlice ( u64 ) ,
@@ -626,13 +625,10 @@ impl<'tcx> Constructor<'tcx> {
626
625
}
627
626
628
627
fn is_integral_range ( & self ) -> bool {
629
- let ty = match self {
630
- ConstantValue ( value, _) => value. ty ,
631
- ConstantRange ( _, _, ty, _, _) => ty,
628
+ match self {
632
629
IntRange ( _) => return true ,
633
630
_ => return false ,
634
631
} ;
635
- IntRange :: is_integral ( ty)
636
632
}
637
633
638
634
fn variant_index_for_adt < ' a > (
@@ -659,7 +655,7 @@ impl<'tcx> Constructor<'tcx> {
659
655
param_env : ty:: ParamEnv < ' tcx > ,
660
656
other_ctors : & Vec < Constructor < ' tcx > > ,
661
657
) -> Vec < Constructor < ' tcx > > {
662
- match * self {
658
+ match self {
663
659
// Those constructors can only match themselves.
664
660
Single | Variant ( _) => {
665
661
if other_ctors. iter ( ) . any ( |c| c == self ) {
@@ -668,7 +664,7 @@ impl<'tcx> Constructor<'tcx> {
668
664
vec ! [ self . clone( ) ]
669
665
}
670
666
}
671
- FixedLenSlice ( self_len) => {
667
+ & FixedLenSlice ( self_len) => {
672
668
let overlaps = |c : & Constructor < ' _ > | match * c {
673
669
FixedLenSlice ( other_len) => other_len == self_len,
674
670
VarLenSlice ( prefix, suffix) => prefix + suffix <= self_len,
@@ -739,41 +735,39 @@ impl<'tcx> Constructor<'tcx> {
739
735
740
736
remaining_ctors
741
737
}
742
- IntRange ( ..) | ConstantRange ( ..) | ConstantValue ( ..) => {
743
- if let Some ( self_range) = IntRange :: from_ctor ( tcx, param_env, self ) {
744
- let mut remaining_ranges = vec ! [ self_range. clone( ) ] ;
745
- let other_ranges = other_ctors
746
- . into_iter ( )
747
- . filter_map ( |c| IntRange :: from_ctor ( tcx, param_env, c) ) ;
748
- for other_range in other_ranges {
749
- if other_range == self_range {
750
- // If the `self` range appears directly in a `match` arm, we can
751
- // eliminate it straight away.
752
- remaining_ranges = vec ! [ ] ;
753
- } else {
754
- // Otherwise explicitely compute the remaining ranges.
755
- remaining_ranges = other_range. subtract_from ( remaining_ranges) ;
756
- }
738
+ IntRange ( self_range) => {
739
+ let mut remaining_ranges = vec ! [ self_range. clone( ) ] ;
740
+ let other_ranges =
741
+ other_ctors. into_iter ( ) . filter_map ( |c| IntRange :: from_ctor ( tcx, param_env, c) ) ;
742
+ for other_range in other_ranges {
743
+ if other_range == * self_range {
744
+ // If the `self` range appears directly in a `match` arm, we can
745
+ // eliminate it straight away.
746
+ remaining_ranges = vec ! [ ] ;
747
+ } else {
748
+ // Otherwise explicitely compute the remaining ranges.
749
+ remaining_ranges = other_range. subtract_from ( remaining_ranges) ;
750
+ }
757
751
758
- // If the ranges that have been considered so far already cover the entire
759
- // range of values, we can return early.
760
- if remaining_ranges. is_empty ( ) {
761
- break ;
762
- }
752
+ // If the ranges that have been considered so far already cover the entire
753
+ // range of values, we can return early.
754
+ if remaining_ranges. is_empty ( ) {
755
+ break ;
763
756
}
757
+ }
764
758
765
- // Convert the ranges back into constructors
766
- remaining_ranges. into_iter ( ) . map ( IntRange ) . collect ( )
759
+ // Convert the ranges back into constructors
760
+ remaining_ranges. into_iter ( ) . map ( IntRange ) . collect ( )
761
+ }
762
+ ConstantRange ( ..) | ConstantValue ( ..) => {
763
+ if other_ctors. iter ( ) . any ( |c| {
764
+ c == self
765
+ // FIXME(Nadrieril): This condition looks fishy
766
+ || IntRange :: from_ctor ( tcx, param_env, c) . is_some ( )
767
+ } ) {
768
+ vec ! [ ]
767
769
} else {
768
- if other_ctors. iter ( ) . any ( |c| {
769
- c == self
770
- // FIXME(Nadrieril): This condition looks fishy
771
- || IntRange :: from_ctor ( tcx, param_env, c) . is_some ( )
772
- } ) {
773
- vec ! [ ]
774
- } else {
775
- vec ! [ self . clone( ) ]
776
- }
770
+ vec ! [ self . clone( ) ]
777
771
}
778
772
}
779
773
}
@@ -1233,6 +1227,10 @@ impl<'tcx> IntRange<'tcx> {
1233
1227
}
1234
1228
}
1235
1229
1230
+ fn is_singleton ( & self ) -> bool {
1231
+ self . range . start ( ) == self . range . end ( )
1232
+ }
1233
+
1236
1234
fn should_treat_range_exhaustively ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> bool {
1237
1235
// Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching`
1238
1236
// feature is enabled.
@@ -1309,15 +1307,13 @@ impl<'tcx> IntRange<'tcx> {
1309
1307
}
1310
1308
1311
1309
fn from_ctor (
1312
- tcx : TyCtxt < ' tcx > ,
1313
- param_env : ty:: ParamEnv < ' tcx > ,
1310
+ _tcx : TyCtxt < ' tcx > ,
1311
+ _param_env : ty:: ParamEnv < ' tcx > ,
1314
1312
ctor : & Constructor < ' tcx > ,
1315
1313
) -> Option < IntRange < ' tcx > > {
1316
1314
// Floating-point ranges are permitted and we don't want
1317
1315
// to consider them when constructing integer ranges.
1318
1316
match ctor {
1319
- ConstantRange ( lo, hi, ty, end, span) => Self :: from_range ( tcx, * lo, * hi, ty, end, * span) ,
1320
- ConstantValue ( val, span) => Self :: from_const ( tcx, param_env, val, * span) ,
1321
1317
IntRange ( range) => Some ( range. clone ( ) ) ,
1322
1318
_ => None ,
1323
1319
}
@@ -1736,14 +1732,23 @@ fn pat_constructor<'tcx>(
1736
1732
PatKind :: Variant { adt_def, variant_index, .. } => {
1737
1733
Some ( Variant ( adt_def. variants [ variant_index] . def_id ) )
1738
1734
}
1739
- PatKind :: Constant { value } => Some ( ConstantValue ( value, pat. span ) ) ,
1740
- PatKind :: Range ( PatRange { lo, hi, end } ) => Some ( ConstantRange (
1741
- lo. eval_bits ( tcx, param_env, lo. ty ) ,
1742
- hi. eval_bits ( tcx, param_env, hi. ty ) ,
1743
- lo. ty ,
1744
- end,
1745
- pat. span ,
1746
- ) ) ,
1735
+ PatKind :: Constant { value } => {
1736
+ if let Some ( int_range) = IntRange :: from_const ( tcx, param_env, value, pat. span ) {
1737
+ Some ( IntRange ( int_range) )
1738
+ } else {
1739
+ Some ( ConstantValue ( value, pat. span ) )
1740
+ }
1741
+ }
1742
+ PatKind :: Range ( PatRange { lo, hi, end } ) => {
1743
+ let ty = lo. ty ;
1744
+ let lo = lo. eval_bits ( tcx, param_env, lo. ty ) ;
1745
+ let hi = hi. eval_bits ( tcx, param_env, hi. ty ) ;
1746
+ if let Some ( int_range) = IntRange :: from_range ( tcx, lo, hi, ty, & end, pat. span ) {
1747
+ Some ( IntRange ( int_range) )
1748
+ } else {
1749
+ Some ( ConstantRange ( lo, hi, ty, end, pat. span ) )
1750
+ }
1751
+ }
1747
1752
PatKind :: Array { .. } => match pat. ty . kind {
1748
1753
ty:: Array ( _, length) => Some ( FixedLenSlice ( length. eval_usize ( tcx, param_env) ) ) ,
1749
1754
_ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , pat. ty) ,
@@ -1874,13 +1879,13 @@ fn split_grouped_constructors<'p, 'tcx>(
1874
1879
1875
1880
for ctor in ctors. into_iter ( ) {
1876
1881
match ctor {
1877
- IntRange ( .. ) | ConstantRange ( .. )
1878
- if IntRange :: should_treat_range_exhaustively ( tcx , ty ) =>
1879
- {
1880
- // We only care about finding all the subranges within the range of the constructor
1881
- // range. Anything else is irrelevant, because it is guaranteed to result in
1882
- // `NotUseful`, which is the default case anyway, and can be ignored.
1883
- let ctor_range = IntRange :: from_ctor ( tcx , param_env , & ctor ) . unwrap ( ) ;
1882
+ IntRange ( ctor_range ) if IntRange :: should_treat_range_exhaustively ( tcx , ty ) => {
1883
+ // Fast-track if the range is trivial. In particular, don't do the overlapping
1884
+ // ranges check.
1885
+ if ctor_range . is_singleton ( ) {
1886
+ split_ctors . push ( IntRange ( ctor_range ) ) ;
1887
+ continue ;
1888
+ }
1884
1889
1885
1890
/// Represents a border between 2 integers. Because the intervals spanning borders
1886
1891
/// must be able to cover every integer, we need to be able to represent
0 commit comments