@@ -593,8 +593,7 @@ enum Constructor<'tcx> {
593
593
ConstantValue ( & ' tcx ty:: Const < ' tcx > , Span ) ,
594
594
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
595
595
IntRange ( IntRange < ' tcx > ) ,
596
- // TODO: non-integer
597
- /// Ranges of literal values (`2.0..=5.2`).
596
+ /// Ranges of non-integer literal values (`2.0..=5.2`).
598
597
ConstantRange ( u128 , u128 , Ty < ' tcx > , RangeEnd , Span ) ,
599
598
/// Array patterns of length `n`.
600
599
FixedLenSlice ( u64 ) ,
@@ -636,13 +635,10 @@ impl<'tcx> Constructor<'tcx> {
636
635
}
637
636
638
637
fn is_integral_range ( & self ) -> bool {
639
- let ty = match self {
640
- ConstantValue ( value, _) => value. ty ,
641
- ConstantRange ( _, _, ty, _, _) => ty,
638
+ match self {
642
639
IntRange ( _) => return true ,
643
640
_ => return false ,
644
641
} ;
645
- IntRange :: is_integral ( ty)
646
642
}
647
643
648
644
fn variant_index_for_adt < ' a > (
@@ -669,7 +665,7 @@ impl<'tcx> Constructor<'tcx> {
669
665
param_env : ty:: ParamEnv < ' tcx > ,
670
666
other_ctors : & Vec < Constructor < ' tcx > > ,
671
667
) -> Vec < Constructor < ' tcx > > {
672
- match * self {
668
+ match self {
673
669
// Those constructors can only match themselves.
674
670
Single | Variant ( _) => {
675
671
if other_ctors. iter ( ) . any ( |c| c == self ) {
@@ -678,7 +674,7 @@ impl<'tcx> Constructor<'tcx> {
678
674
vec ! [ self . clone( ) ]
679
675
}
680
676
}
681
- FixedLenSlice ( self_len) => {
677
+ & FixedLenSlice ( self_len) => {
682
678
let overlaps = |c : & Constructor < ' _ > | match * c {
683
679
FixedLenSlice ( other_len) => other_len == self_len,
684
680
VarLenSlice ( prefix, suffix) => prefix + suffix <= self_len,
@@ -749,41 +745,39 @@ impl<'tcx> Constructor<'tcx> {
749
745
750
746
remaining_ctors
751
747
}
752
- IntRange ( ..) | ConstantRange ( ..) | ConstantValue ( ..) => {
753
- if let Some ( self_range) = IntRange :: from_ctor ( tcx, param_env, self ) {
754
- let mut remaining_ranges = vec ! [ self_range. clone( ) ] ;
755
- let other_ranges = other_ctors
756
- . into_iter ( )
757
- . filter_map ( |c| IntRange :: from_ctor ( tcx, param_env, c) ) ;
758
- for other_range in other_ranges {
759
- if other_range == self_range {
760
- // If the `self` range appears directly in a `match` arm, we can
761
- // eliminate it straight away.
762
- remaining_ranges = vec ! [ ] ;
763
- } else {
764
- // Otherwise explicitely compute the remaining ranges.
765
- remaining_ranges = other_range. subtract_from ( remaining_ranges) ;
766
- }
748
+ IntRange ( self_range) => {
749
+ let mut remaining_ranges = vec ! [ self_range. clone( ) ] ;
750
+ let other_ranges =
751
+ other_ctors. into_iter ( ) . filter_map ( |c| IntRange :: from_ctor ( tcx, param_env, c) ) ;
752
+ for other_range in other_ranges {
753
+ if other_range == * self_range {
754
+ // If the `self` range appears directly in a `match` arm, we can
755
+ // eliminate it straight away.
756
+ remaining_ranges = vec ! [ ] ;
757
+ } else {
758
+ // Otherwise explicitely compute the remaining ranges.
759
+ remaining_ranges = other_range. subtract_from ( remaining_ranges) ;
760
+ }
767
761
768
- // If the ranges that have been considered so far already cover the entire
769
- // range of values, we can return early.
770
- if remaining_ranges. is_empty ( ) {
771
- break ;
772
- }
762
+ // If the ranges that have been considered so far already cover the entire
763
+ // range of values, we can return early.
764
+ if remaining_ranges. is_empty ( ) {
765
+ break ;
773
766
}
767
+ }
774
768
775
- // Convert the ranges back into constructors
776
- remaining_ranges. into_iter ( ) . map ( IntRange ) . collect ( )
769
+ // Convert the ranges back into constructors
770
+ remaining_ranges. into_iter ( ) . map ( IntRange ) . collect ( )
771
+ }
772
+ ConstantRange ( ..) | ConstantValue ( ..) => {
773
+ if other_ctors. iter ( ) . any ( |c| {
774
+ c == self
775
+ // FIXME(Nadrieril): This condition looks fishy
776
+ || IntRange :: from_ctor ( tcx, param_env, c) . is_some ( )
777
+ } ) {
778
+ vec ! [ ]
777
779
} else {
778
- if other_ctors. iter ( ) . any ( |c| {
779
- c == self
780
- // FIXME(Nadrieril): This condition looks fishy
781
- || IntRange :: from_ctor ( tcx, param_env, c) . is_some ( )
782
- } ) {
783
- vec ! [ ]
784
- } else {
785
- vec ! [ self . clone( ) ]
786
- }
780
+ vec ! [ self . clone( ) ]
787
781
}
788
782
}
789
783
// This constructor is never covered by anything else
@@ -1285,6 +1279,10 @@ impl<'tcx> IntRange<'tcx> {
1285
1279
}
1286
1280
}
1287
1281
1282
+ fn is_singleton ( & self ) -> bool {
1283
+ self . range . start ( ) == self . range . end ( )
1284
+ }
1285
+
1288
1286
fn should_treat_range_exhaustively ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> bool {
1289
1287
// Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching`
1290
1288
// feature is enabled.
@@ -1363,15 +1361,13 @@ impl<'tcx> IntRange<'tcx> {
1363
1361
}
1364
1362
1365
1363
fn from_ctor (
1366
- tcx : TyCtxt < ' tcx > ,
1367
- param_env : ty:: ParamEnv < ' tcx > ,
1364
+ _tcx : TyCtxt < ' tcx > ,
1365
+ _param_env : ty:: ParamEnv < ' tcx > ,
1368
1366
ctor : & Constructor < ' tcx > ,
1369
1367
) -> Option < IntRange < ' tcx > > {
1370
1368
// Floating-point ranges are permitted and we don't want
1371
1369
// to consider them when constructing integer ranges.
1372
1370
match ctor {
1373
- ConstantRange ( lo, hi, ty, end, span) => Self :: from_range ( tcx, * lo, * hi, ty, end, * span) ,
1374
- ConstantValue ( val, span) => Self :: from_const ( tcx, param_env, val, * span) ,
1375
1371
IntRange ( range) => Some ( range. clone ( ) ) ,
1376
1372
_ => None ,
1377
1373
}
@@ -1747,14 +1743,23 @@ fn pat_constructor<'tcx>(
1747
1743
PatKind :: Variant { adt_def, variant_index, .. } => {
1748
1744
Some ( Variant ( adt_def. variants [ variant_index] . def_id ) )
1749
1745
}
1750
- PatKind :: Constant { value } => Some ( ConstantValue ( value, pat. span ) ) ,
1751
- PatKind :: Range ( PatRange { lo, hi, end } ) => Some ( ConstantRange (
1752
- lo. eval_bits ( tcx, param_env, lo. ty ) ,
1753
- hi. eval_bits ( tcx, param_env, hi. ty ) ,
1754
- lo. ty ,
1755
- end,
1756
- pat. span ,
1757
- ) ) ,
1746
+ PatKind :: Constant { value } => {
1747
+ if let Some ( int_range) = IntRange :: from_const ( tcx, param_env, value, pat. span ) {
1748
+ Some ( IntRange ( int_range) )
1749
+ } else {
1750
+ Some ( ConstantValue ( value, pat. span ) )
1751
+ }
1752
+ }
1753
+ PatKind :: Range ( PatRange { lo, hi, end } ) => {
1754
+ let ty = lo. ty ;
1755
+ let lo = lo. eval_bits ( tcx, param_env, lo. ty ) ;
1756
+ let hi = hi. eval_bits ( tcx, param_env, hi. ty ) ;
1757
+ if let Some ( int_range) = IntRange :: from_range ( tcx, lo, hi, ty, & end, pat. span ) {
1758
+ Some ( IntRange ( int_range) )
1759
+ } else {
1760
+ Some ( ConstantRange ( lo, hi, ty, end, pat. span ) )
1761
+ }
1762
+ }
1758
1763
PatKind :: Array { .. } => match pat. ty . kind {
1759
1764
ty:: Array ( _, length) => Some ( FixedLenSlice ( length. eval_usize ( tcx, param_env) ) ) ,
1760
1765
_ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , pat. ty) ,
@@ -1897,13 +1902,13 @@ fn split_grouped_constructors<'p, 'tcx>(
1897
1902
1898
1903
for ctor in ctors. into_iter ( ) {
1899
1904
match ctor {
1900
- IntRange ( .. ) | ConstantRange ( .. )
1901
- if IntRange :: should_treat_range_exhaustively ( tcx , ty ) =>
1902
- {
1903
- // We only care about finding all the subranges within the range of the constructor
1904
- // range. Anything else is irrelevant, because it is guaranteed to result in
1905
- // `NotUseful`, which is the default case anyway, and can be ignored.
1906
- let ctor_range = IntRange :: from_ctor ( tcx , param_env , & ctor ) . unwrap ( ) ;
1905
+ IntRange ( ctor_range ) if IntRange :: should_treat_range_exhaustively ( tcx , ty ) => {
1906
+ // Fast-track if the range is trivial. In particular, don't do the overlapping
1907
+ // ranges check.
1908
+ if ctor_range . is_singleton ( ) {
1909
+ split_ctors . push ( IntRange ( ctor_range ) ) ;
1910
+ continue ;
1911
+ }
1907
1912
1908
1913
/// Represents a border between 2 integers. Because the intervals spanning borders
1909
1914
/// must be able to cover every integer, we need to be able to represent
0 commit comments