@@ -593,8 +593,7 @@ enum Constructor<'tcx> {
593593 ConstantValue ( & ' tcx ty:: Const < ' tcx > , Span ) ,
594594 /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
595595 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`).
598597 ConstantRange ( u128 , u128 , Ty < ' tcx > , RangeEnd , Span ) ,
599598 /// Array patterns of length `n`.
600599 FixedLenSlice ( u64 ) ,
@@ -636,13 +635,10 @@ impl<'tcx> Constructor<'tcx> {
636635 }
637636
638637 fn is_integral_range ( & self ) -> bool {
639- let ty = match self {
640- ConstantValue ( value, _) => value. ty ,
641- ConstantRange ( _, _, ty, _, _) => ty,
638+ match self {
642639 IntRange ( _) => return true ,
643640 _ => return false ,
644641 } ;
645- IntRange :: is_integral ( ty)
646642 }
647643
648644 fn variant_index_for_adt < ' a > (
@@ -669,7 +665,7 @@ impl<'tcx> Constructor<'tcx> {
669665 param_env : ty:: ParamEnv < ' tcx > ,
670666 other_ctors : & Vec < Constructor < ' tcx > > ,
671667 ) -> Vec < Constructor < ' tcx > > {
672- match * self {
668+ match self {
673669 // Those constructors can only match themselves.
674670 Single | Variant ( _) => {
675671 if other_ctors. iter ( ) . any ( |c| c == self ) {
@@ -678,7 +674,7 @@ impl<'tcx> Constructor<'tcx> {
678674 vec ! [ self . clone( ) ]
679675 }
680676 }
681- FixedLenSlice ( self_len) => {
677+ & FixedLenSlice ( self_len) => {
682678 let overlaps = |c : & Constructor < ' _ > | match * c {
683679 FixedLenSlice ( other_len) => other_len == self_len,
684680 VarLenSlice ( prefix, suffix) => prefix + suffix <= self_len,
@@ -749,41 +745,39 @@ impl<'tcx> Constructor<'tcx> {
749745
750746 remaining_ctors
751747 }
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+ }
767761
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 ;
773766 }
767+ }
774768
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 ! [ ]
777779 } 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( ) ]
787781 }
788782 }
789783 // This constructor is never covered by anything else
@@ -1285,6 +1279,10 @@ impl<'tcx> IntRange<'tcx> {
12851279 }
12861280 }
12871281
1282+ fn is_singleton ( & self ) -> bool {
1283+ self . range . start ( ) == self . range . end ( )
1284+ }
1285+
12881286 fn should_treat_range_exhaustively ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> bool {
12891287 // Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching`
12901288 // feature is enabled.
@@ -1363,15 +1361,13 @@ impl<'tcx> IntRange<'tcx> {
13631361 }
13641362
13651363 fn from_ctor (
1366- tcx : TyCtxt < ' tcx > ,
1367- param_env : ty:: ParamEnv < ' tcx > ,
1364+ _tcx : TyCtxt < ' tcx > ,
1365+ _param_env : ty:: ParamEnv < ' tcx > ,
13681366 ctor : & Constructor < ' tcx > ,
13691367 ) -> Option < IntRange < ' tcx > > {
13701368 // Floating-point ranges are permitted and we don't want
13711369 // to consider them when constructing integer ranges.
13721370 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) ,
13751371 IntRange ( range) => Some ( range. clone ( ) ) ,
13761372 _ => None ,
13771373 }
@@ -1747,14 +1743,23 @@ fn pat_constructor<'tcx>(
17471743 PatKind :: Variant { adt_def, variant_index, .. } => {
17481744 Some ( Variant ( adt_def. variants [ variant_index] . def_id ) )
17491745 }
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+ }
17581763 PatKind :: Array { .. } => match pat. ty . kind {
17591764 ty:: Array ( _, length) => Some ( FixedLenSlice ( length. eval_usize ( tcx, param_env) ) ) ,
17601765 _ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , pat. ty) ,
@@ -1897,13 +1902,13 @@ fn split_grouped_constructors<'p, 'tcx>(
18971902
18981903 for ctor in ctors. into_iter ( ) {
18991904 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+ }
19071912
19081913 /// Represents a border between 2 integers. Because the intervals spanning borders
19091914 /// must be able to cover every integer, we need to be able to represent
0 commit comments