@@ -585,7 +585,9 @@ enum Constructor<'tcx> {
585585 FixedLenSlice ( u64 ) ,
586586
587587 // Meta-constructors
588- /// Ranges of literal values (`2..=5` and `2..5`).
588+ /// Ranges of integer literal values (`2..=5` and `2..5`).
589+ IntRange ( IntRange < ' tcx > ) ,
590+ /// Ranges of non-integer literal values (`2.0..=5.2`).
589591 ConstantRange ( & ' tcx ty:: Const < ' tcx > , & ' tcx ty:: Const < ' tcx > , RangeEnd ) ,
590592 /// Slice patterns. Captures any array constructor of length >= i+j.
591593 VarLenSlice ( u64 , u64 ) ,
@@ -647,8 +649,8 @@ impl<'tcx> Constructor<'tcx> {
647649 match self {
648650 // Any base constructor can be used unchanged.
649651 Single | Variant ( _) | ConstantValue ( _) | FixedLenSlice ( _) => smallvec ! [ self ] ,
650- ConstantRange ( ref lo , ..)
651- if IntRange :: should_treat_range_exhaustively ( cx. tcx , lo . ty ) =>
652+ ConstantRange ( .. ) | IntRange ( ..)
653+ if IntRange :: should_treat_range_exhaustively ( cx. tcx , ty) =>
652654 {
653655 // Splitting up a range naïvely would mean creating a separate constructor for
654656 // every single value in the range, which is clearly impractical. We therefore want
@@ -734,7 +736,7 @@ impl<'tcx> Constructor<'tcx> {
734736 . map ( |range| IntRange :: range_to_ctor ( cx. tcx , ty, range) )
735737 . collect ( )
736738 }
737- ConstantRange ( ..) => smallvec ! [ self ] ,
739+ ConstantRange ( ..) | IntRange ( .. ) => smallvec ! [ self ] ,
738740 VarLenSlice ( self_prefix, self_suffix) => {
739741 // A variable-length slice pattern is matched by an infinite collection of
740742 // fixed-length array patterns. However it turns out that for each finite set of
@@ -1045,7 +1047,7 @@ impl<'tcx> Constructor<'tcx> {
10451047
10461048 remaining_ctors
10471049 }
1048- ConstantRange ( ..) | ConstantValue ( ..) => {
1050+ ConstantRange ( ..) | ConstantValue ( ..) | IntRange ( .. ) => {
10491051 let mut remaining_ctors = smallvec ! [ self ] ;
10501052
10511053 // For each used ctor, subtract from the current set of constructors.
@@ -1137,7 +1139,11 @@ impl<'tcx> Constructor<'tcx> {
11371139 ty:: Slice ( ty) | ty:: Array ( ty, _) => ( 0 ..prefix + suffix) . map ( |_| ty) . collect ( ) ,
11381140 _ => bug ! ( "bad slice pattern {:?} {:?}" , self , ty) ,
11391141 } ,
1140- ConstantValue ( _) | MissingConstructors ( _) | ConstantRange ( ..) | Wildcard => vec ! [ ] ,
1142+ ConstantValue ( _)
1143+ | MissingConstructors ( _)
1144+ | ConstantRange ( ..)
1145+ | IntRange ( ..)
1146+ | Wildcard => vec ! [ ] ,
11411147 } ;
11421148
11431149 subpattern_types. into_iter ( ) . map ( |ty| Pat { ty, span : DUMMY_SP , kind : box PatKind :: Wild } )
@@ -1162,7 +1168,11 @@ impl<'tcx> Constructor<'tcx> {
11621168 } ,
11631169 FixedLenSlice ( length) => length,
11641170 VarLenSlice ( prefix, suffix) => prefix + suffix,
1165- ConstantValue ( _) | ConstantRange ( ..) | Wildcard | MissingConstructors ( _) => 0 ,
1171+ ConstantValue ( _)
1172+ | ConstantRange ( ..)
1173+ | IntRange ( ..)
1174+ | Wildcard
1175+ | MissingConstructors ( _) => 0 ,
11661176 }
11671177 }
11681178
@@ -1230,6 +1240,7 @@ impl<'tcx> Constructor<'tcx> {
12301240 } ,
12311241 ConstantValue ( value) => PatKind :: Constant { value } ,
12321242 ConstantRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
1243+ IntRange ( ref range) => range. to_patkind ( cx. tcx ) ,
12331244 Wildcard => PatKind :: Wild ,
12341245 MissingConstructors ( ref missing_ctors) => {
12351246 // Construct for each missing constructor a "wildcard" version of this
@@ -1424,8 +1435,26 @@ fn all_constructors<'a, 'tcx>(
14241435 let to_const = |x| ty:: Const :: from_bits ( cx. tcx , x as u128 , param_env) ;
14251436 vec ! [
14261437 // The valid Unicode Scalar Value ranges.
1427- ConstantRange ( to_const( '\u{0000}' ) , to_const( '\u{D7FF}' ) , RangeEnd :: Included ) ,
1428- ConstantRange ( to_const( '\u{E000}' ) , to_const( '\u{10FFFF}' ) , RangeEnd :: Included ) ,
1438+ IntRange (
1439+ IntRange :: from_range(
1440+ cx. tcx,
1441+ cx. param_env,
1442+ to_const( '\u{0000}' ) ,
1443+ to_const( '\u{D7FF}' ) ,
1444+ & RangeEnd :: Included ,
1445+ )
1446+ . unwrap( ) ,
1447+ ) ,
1448+ IntRange (
1449+ IntRange :: from_range(
1450+ cx. tcx,
1451+ cx. param_env,
1452+ to_const( '\u{E000}' ) ,
1453+ to_const( '\u{10FFFF}' ) ,
1454+ & RangeEnd :: Included ,
1455+ )
1456+ . unwrap( ) ,
1457+ ) ,
14291458 ]
14301459 }
14311460 ty:: Int ( ity) => {
@@ -1434,14 +1463,32 @@ fn all_constructors<'a, 'tcx>(
14341463 let bits = Integer :: from_attr ( & cx. tcx , SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
14351464 let min = 1u128 << ( bits - 1 ) ;
14361465 let max = min - 1 ;
1437- vec ! [ ConstantRange ( to_const( min) , to_const( max) , RangeEnd :: Included ) ]
1466+ vec ! [ IntRange (
1467+ IntRange :: from_range(
1468+ cx. tcx,
1469+ cx. param_env,
1470+ to_const( min) ,
1471+ to_const( max) ,
1472+ & RangeEnd :: Included ,
1473+ )
1474+ . unwrap( ) ,
1475+ ) ]
14381476 }
14391477 ty:: Uint ( uty) => {
14401478 let param_env = ty:: ParamEnv :: empty ( ) . and ( ty) ;
14411479 let to_const = |x| ty:: Const :: from_bits ( cx. tcx , x, param_env) ;
14421480 let size = Integer :: from_attr ( & cx. tcx , UnsignedInt ( uty) ) . size ( ) ;
14431481 let max = truncate ( u128:: max_value ( ) , size) ;
1444- vec ! [ ConstantRange ( to_const( 0 ) , to_const( max) , RangeEnd :: Included ) ]
1482+ vec ! [ IntRange (
1483+ IntRange :: from_range(
1484+ cx. tcx,
1485+ cx. param_env,
1486+ to_const( 0 ) ,
1487+ to_const( max) ,
1488+ & RangeEnd :: Included ,
1489+ )
1490+ . unwrap( ) ,
1491+ ) ]
14451492 }
14461493 _ => {
14471494 if cx. is_uninhabited ( ty) {
@@ -1464,7 +1511,7 @@ fn all_constructors<'a, 'tcx>(
14641511///
14651512/// `IntRange` is never used to encode an empty range or a "range" that wraps
14661513/// around the (offset) space: i.e., `range.lo <= range.hi`.
1467- #[ derive( Clone ) ]
1514+ #[ derive( Debug , Clone , PartialEq ) ]
14681515struct IntRange < ' tcx > {
14691516 pub range : RangeInclusive < u128 > ,
14701517 pub ty : Ty < ' tcx > ,
@@ -1563,6 +1610,7 @@ impl<'tcx> IntRange<'tcx> {
15631610 // Floating-point ranges are permitted and we don't want
15641611 // to consider them when constructing integer ranges.
15651612 match ctor {
1613+ IntRange ( range) => Some ( range. clone ( ) ) ,
15661614 ConstantRange ( lo, hi, end) => Self :: from_range ( tcx, param_env, lo, hi, end) ,
15671615 ConstantValue ( val) => Self :: from_const ( tcx, param_env, val) ,
15681616 _ => None ,
@@ -1580,21 +1628,30 @@ impl<'tcx> IntRange<'tcx> {
15801628 }
15811629 }
15821630
1583- /// Converts a `RangeInclusive` to a `ConstantValue` or inclusive `ConstantRange `.
1631+ /// Converts a `RangeInclusive` to a `Constructor `.
15841632 fn range_to_ctor (
1585- tcx : TyCtxt < ' tcx > ,
1633+ _tcx : TyCtxt < ' tcx > ,
15861634 ty : Ty < ' tcx > ,
1587- r : RangeInclusive < u128 > ,
1635+ range : RangeInclusive < u128 > ,
15881636 ) -> Constructor < ' tcx > {
1589- let bias = IntRange :: signed_bias ( tcx, ty) ;
1590- let ( lo, hi) = r. into_inner ( ) ;
1637+ IntRange ( IntRange { ty, range } )
1638+ }
1639+
1640+ /// Converts an `IntRange` to a `PatKind::Constant` or inclusive `PatKind::Range`.
1641+ fn to_patkind ( & self , tcx : TyCtxt < ' tcx > ) -> PatKind < ' tcx > {
1642+ let bias = IntRange :: signed_bias ( tcx, self . ty ) ;
1643+ let ( lo, hi) = self . range . clone ( ) . into_inner ( ) ;
15911644 if lo == hi {
1592- let ty = ty:: ParamEnv :: empty ( ) . and ( ty) ;
1593- ConstantValue ( ty:: Const :: from_bits ( tcx, lo ^ bias, ty) )
1645+ let ty = ty:: ParamEnv :: empty ( ) . and ( self . ty ) ;
1646+ PatKind :: Constant { value : ty:: Const :: from_bits ( tcx, lo ^ bias, ty) }
15941647 } else {
1595- let param_env = ty:: ParamEnv :: empty ( ) . and ( ty) ;
1648+ let param_env = ty:: ParamEnv :: empty ( ) . and ( self . ty ) ;
15961649 let to_const = |x| ty:: Const :: from_bits ( tcx, x, param_env) ;
1597- ConstantRange ( to_const ( lo ^ bias) , to_const ( hi ^ bias) , RangeEnd :: Included )
1650+ PatKind :: Range ( PatRange {
1651+ lo : to_const ( lo ^ bias) ,
1652+ hi : to_const ( hi ^ bias) ,
1653+ end : RangeEnd :: Included ,
1654+ } )
15981655 }
15991656 }
16001657
@@ -1851,8 +1908,20 @@ fn pat_constructors<'tcx>(
18511908 PatKind :: Variant { adt_def, variant_index, .. } => {
18521909 smallvec ! [ Variant ( adt_def. variants[ variant_index] . def_id) ]
18531910 }
1854- PatKind :: Constant { value } => smallvec ! [ ConstantValue ( value) ] ,
1855- PatKind :: Range ( PatRange { lo, hi, end } ) => smallvec ! [ ConstantRange ( lo, hi, end) ] ,
1911+ PatKind :: Constant { value } => {
1912+ if let Some ( range) = IntRange :: from_const ( tcx, param_env, value) {
1913+ smallvec ! [ IntRange ( range) ]
1914+ } else {
1915+ smallvec ! [ ConstantValue ( value) ]
1916+ }
1917+ }
1918+ PatKind :: Range ( PatRange { lo, hi, end } ) => {
1919+ if let Some ( range) = IntRange :: from_range ( tcx, param_env, & lo, & hi, & end) {
1920+ smallvec ! [ IntRange ( range) ]
1921+ } else {
1922+ smallvec ! [ ConstantRange ( lo, hi, end) ]
1923+ }
1924+ }
18561925 PatKind :: Array { .. } => match ty. kind {
18571926 ty:: Array ( _, length) => smallvec ! [ FixedLenSlice ( length. eval_usize( tcx, param_env) ) ] ,
18581927 _ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , ty) ,
@@ -1935,6 +2004,7 @@ fn slice_pat_covered_by_const<'tcx>(
19352004// Whether a constructor is a range or constant with an integer type.
19362005fn is_integral_range ( ctor : & Constructor < ' tcx > ) -> bool {
19372006 let ty = match ctor {
2007+ IntRange ( _) => return true ,
19382008 ConstantValue ( value) => value. ty ,
19392009 ConstantRange ( lo, _, _) => lo. ty ,
19402010 _ => return false ,
0 commit comments