@@ -585,7 +585,9 @@ enum Constructor<'tcx> {
585
585
FixedLenSlice ( u64 ) ,
586
586
587
587
// 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`).
589
591
ConstantRange ( & ' tcx ty:: Const < ' tcx > , & ' tcx ty:: Const < ' tcx > , RangeEnd ) ,
590
592
/// Slice patterns. Captures any array constructor of length >= i+j.
591
593
VarLenSlice ( u64 , u64 ) ,
@@ -647,8 +649,8 @@ impl<'tcx> Constructor<'tcx> {
647
649
match self {
648
650
// Any base constructor can be used unchanged.
649
651
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) =>
652
654
{
653
655
// Splitting up a range naïvely would mean creating a separate constructor for
654
656
// every single value in the range, which is clearly impractical. We therefore want
@@ -734,7 +736,7 @@ impl<'tcx> Constructor<'tcx> {
734
736
. map ( |range| IntRange :: range_to_ctor ( cx. tcx , ty, range) )
735
737
. collect ( )
736
738
}
737
- ConstantRange ( ..) => smallvec ! [ self ] ,
739
+ ConstantRange ( ..) | IntRange ( .. ) => smallvec ! [ self ] ,
738
740
VarLenSlice ( self_prefix, self_suffix) => {
739
741
// A variable-length slice pattern is matched by an infinite collection of
740
742
// fixed-length array patterns. However it turns out that for each finite set of
@@ -1045,7 +1047,7 @@ impl<'tcx> Constructor<'tcx> {
1045
1047
1046
1048
remaining_ctors
1047
1049
}
1048
- ConstantRange ( ..) | ConstantValue ( ..) => {
1050
+ ConstantRange ( ..) | ConstantValue ( ..) | IntRange ( .. ) => {
1049
1051
let mut remaining_ctors = smallvec ! [ self ] ;
1050
1052
1051
1053
// For each used ctor, subtract from the current set of constructors.
@@ -1137,7 +1139,11 @@ impl<'tcx> Constructor<'tcx> {
1137
1139
ty:: Slice ( ty) | ty:: Array ( ty, _) => ( 0 ..prefix + suffix) . map ( |_| ty) . collect ( ) ,
1138
1140
_ => bug ! ( "bad slice pattern {:?} {:?}" , self , ty) ,
1139
1141
} ,
1140
- ConstantValue ( _) | MissingConstructors ( _) | ConstantRange ( ..) | Wildcard => vec ! [ ] ,
1142
+ ConstantValue ( _)
1143
+ | MissingConstructors ( _)
1144
+ | ConstantRange ( ..)
1145
+ | IntRange ( ..)
1146
+ | Wildcard => vec ! [ ] ,
1141
1147
} ;
1142
1148
1143
1149
subpattern_types. into_iter ( ) . map ( |ty| Pat { ty, span : DUMMY_SP , kind : box PatKind :: Wild } )
@@ -1162,7 +1168,11 @@ impl<'tcx> Constructor<'tcx> {
1162
1168
} ,
1163
1169
FixedLenSlice ( length) => length,
1164
1170
VarLenSlice ( prefix, suffix) => prefix + suffix,
1165
- ConstantValue ( _) | ConstantRange ( ..) | Wildcard | MissingConstructors ( _) => 0 ,
1171
+ ConstantValue ( _)
1172
+ | ConstantRange ( ..)
1173
+ | IntRange ( ..)
1174
+ | Wildcard
1175
+ | MissingConstructors ( _) => 0 ,
1166
1176
}
1167
1177
}
1168
1178
@@ -1230,6 +1240,7 @@ impl<'tcx> Constructor<'tcx> {
1230
1240
} ,
1231
1241
ConstantValue ( value) => PatKind :: Constant { value } ,
1232
1242
ConstantRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
1243
+ IntRange ( ref range) => range. to_patkind ( cx. tcx ) ,
1233
1244
Wildcard => PatKind :: Wild ,
1234
1245
MissingConstructors ( ref missing_ctors) => {
1235
1246
// Construct for each missing constructor a "wildcard" version of this
@@ -1424,8 +1435,26 @@ fn all_constructors<'a, 'tcx>(
1424
1435
let to_const = |x| ty:: Const :: from_bits ( cx. tcx , x as u128 , param_env) ;
1425
1436
vec ! [
1426
1437
// 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
+ ) ,
1429
1458
]
1430
1459
}
1431
1460
ty:: Int ( ity) => {
@@ -1434,14 +1463,32 @@ fn all_constructors<'a, 'tcx>(
1434
1463
let bits = Integer :: from_attr ( & cx. tcx , SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
1435
1464
let min = 1u128 << ( bits - 1 ) ;
1436
1465
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
+ ) ]
1438
1476
}
1439
1477
ty:: Uint ( uty) => {
1440
1478
let param_env = ty:: ParamEnv :: empty ( ) . and ( ty) ;
1441
1479
let to_const = |x| ty:: Const :: from_bits ( cx. tcx , x, param_env) ;
1442
1480
let size = Integer :: from_attr ( & cx. tcx , UnsignedInt ( uty) ) . size ( ) ;
1443
1481
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
+ ) ]
1445
1492
}
1446
1493
_ => {
1447
1494
if cx. is_uninhabited ( ty) {
@@ -1464,7 +1511,7 @@ fn all_constructors<'a, 'tcx>(
1464
1511
///
1465
1512
/// `IntRange` is never used to encode an empty range or a "range" that wraps
1466
1513
/// around the (offset) space: i.e., `range.lo <= range.hi`.
1467
- #[ derive( Clone ) ]
1514
+ #[ derive( Debug , Clone , PartialEq ) ]
1468
1515
struct IntRange < ' tcx > {
1469
1516
pub range : RangeInclusive < u128 > ,
1470
1517
pub ty : Ty < ' tcx > ,
@@ -1563,6 +1610,7 @@ impl<'tcx> IntRange<'tcx> {
1563
1610
// Floating-point ranges are permitted and we don't want
1564
1611
// to consider them when constructing integer ranges.
1565
1612
match ctor {
1613
+ IntRange ( range) => Some ( range. clone ( ) ) ,
1566
1614
ConstantRange ( lo, hi, end) => Self :: from_range ( tcx, param_env, lo, hi, end) ,
1567
1615
ConstantValue ( val) => Self :: from_const ( tcx, param_env, val) ,
1568
1616
_ => None ,
@@ -1580,21 +1628,30 @@ impl<'tcx> IntRange<'tcx> {
1580
1628
}
1581
1629
}
1582
1630
1583
- /// Converts a `RangeInclusive` to a `ConstantValue` or inclusive `ConstantRange `.
1631
+ /// Converts a `RangeInclusive` to a `Constructor `.
1584
1632
fn range_to_ctor (
1585
- tcx : TyCtxt < ' tcx > ,
1633
+ _tcx : TyCtxt < ' tcx > ,
1586
1634
ty : Ty < ' tcx > ,
1587
- r : RangeInclusive < u128 > ,
1635
+ range : RangeInclusive < u128 > ,
1588
1636
) -> 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 ( ) ;
1591
1644
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) }
1594
1647
} else {
1595
- let param_env = ty:: ParamEnv :: empty ( ) . and ( ty) ;
1648
+ let param_env = ty:: ParamEnv :: empty ( ) . and ( self . ty ) ;
1596
1649
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
+ } )
1598
1655
}
1599
1656
}
1600
1657
@@ -1851,8 +1908,20 @@ fn pat_constructors<'tcx>(
1851
1908
PatKind :: Variant { adt_def, variant_index, .. } => {
1852
1909
smallvec ! [ Variant ( adt_def. variants[ variant_index] . def_id) ]
1853
1910
}
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
+ }
1856
1925
PatKind :: Array { .. } => match ty. kind {
1857
1926
ty:: Array ( _, length) => smallvec ! [ FixedLenSlice ( length. eval_usize( tcx, param_env) ) ] ,
1858
1927
_ => span_bug ! ( pat. span, "bad ty {:?} for array pattern" , ty) ,
@@ -1935,6 +2004,7 @@ fn slice_pat_covered_by_const<'tcx>(
1935
2004
// Whether a constructor is a range or constant with an integer type.
1936
2005
fn is_integral_range ( ctor : & Constructor < ' tcx > ) -> bool {
1937
2006
let ty = match ctor {
2007
+ IntRange ( _) => return true ,
1938
2008
ConstantValue ( value) => value. ty ,
1939
2009
ConstantRange ( lo, _, _) => lo. ty ,
1940
2010
_ => return false ,
0 commit comments