@@ -630,17 +630,6 @@ impl<'tcx> Constructor<'tcx> {
630
630
}
631
631
}
632
632
633
- // Whether to evaluate a constructor using exhaustive integer matching. This is true if the
634
- // constructor is a range or constant with an integer type.
635
- fn is_range_and_should_match_exhaustively ( & self , tcx : TyCtxt < ' tcx > ) -> bool {
636
- let ty = match self {
637
- ConstantValue ( value, _) => value. ty ,
638
- ConstantRange ( _, _, ty, _, _) => ty,
639
- _ => return false ,
640
- } ;
641
- IntRange :: should_treat_range_exhaustively ( tcx, ty)
642
- }
643
-
644
633
fn is_integral_range ( & self ) -> bool {
645
634
let ty = match self {
646
635
ConstantValue ( value, _) => value. ty ,
@@ -1468,24 +1457,23 @@ impl<'tcx> IntRange<'tcx> {
1468
1457
remaining_ranges
1469
1458
}
1470
1459
1471
- fn intersection ( & self , other : & Self ) -> Option < Self > {
1460
+ fn intersection ( & self , tcx : TyCtxt < ' tcx > , other : & Self ) -> Option < Self > {
1472
1461
let ty = self . ty ;
1473
1462
let ( lo, hi) = ( * self . range . start ( ) , * self . range . end ( ) ) ;
1474
1463
let ( other_lo, other_hi) = ( * other. range . start ( ) , * other. range . end ( ) ) ;
1475
- if lo <= other_hi && other_lo <= hi {
1476
- let span = other. span ;
1477
- Some ( IntRange { range : max ( lo, other_lo) ..=min ( hi, other_hi) , ty, span } )
1464
+ if Self :: should_treat_range_exhaustively ( tcx, ty) {
1465
+ if lo <= other_hi && other_lo <= hi {
1466
+ let span = other. span ;
1467
+ Some ( IntRange { range : max ( lo, other_lo) ..=min ( hi, other_hi) , ty, span } )
1468
+ } else {
1469
+ None
1470
+ }
1478
1471
} else {
1479
- None
1472
+ // If the range sould not be treated exhaustively, fallback to checking for inclusion.
1473
+ if other_lo <= lo && hi <= other_hi { Some ( self . clone ( ) ) } else { None }
1480
1474
}
1481
1475
}
1482
1476
1483
- fn is_subrange ( & self , other : & Self ) -> bool {
1484
- let ( lo, hi) = ( * self . range . start ( ) , * self . range . end ( ) ) ;
1485
- let ( other_lo, other_hi) = ( * other. range . start ( ) , * other. range . end ( ) ) ;
1486
- other_lo <= lo && hi <= other_hi
1487
- }
1488
-
1489
1477
fn suspicious_intersection ( & self , other : & Self ) -> bool {
1490
1478
// `false` in the following cases:
1491
1479
// 1 ---- // 1 ---------- // 1 ---- // 1 ----
@@ -1913,7 +1901,7 @@ fn split_grouped_constructors<'p, 'tcx>(
1913
1901
1914
1902
for ctor in ctors. into_iter ( ) {
1915
1903
match ctor {
1916
- ConstantRange ( ..) if ctor . is_range_and_should_match_exhaustively ( tcx) => {
1904
+ ConstantRange ( ..) if IntRange :: should_treat_range_exhaustively ( tcx, ty ) => {
1917
1905
// We only care about finding all the subranges within the range of the constructor
1918
1906
// range. Anything else is irrelevant, because it is guaranteed to result in
1919
1907
// `NotUseful`, which is the default case anyway, and can be ignored.
@@ -1951,7 +1939,7 @@ fn split_grouped_constructors<'p, 'tcx>(
1951
1939
IntRange :: from_pat ( tcx, param_env, row. head ( ) ) . map ( |r| ( r, row. len ( ) ) )
1952
1940
} )
1953
1941
. flat_map ( |( range, row_len) | {
1954
- let intersection = ctor_range. intersection ( & range) ;
1942
+ let intersection = ctor_range. intersection ( tcx , & range) ;
1955
1943
let should_lint = ctor_range. suspicious_intersection ( & range) ;
1956
1944
if let ( Some ( range) , 1 , true ) = ( & intersection, row_len, should_lint) {
1957
1945
// FIXME: for now, only check for overlapping ranges on simple range
@@ -2309,12 +2297,12 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2309
2297
// If the constructor is a:
2310
2298
// - Single value: add a row if the pattern contains the constructor.
2311
2299
// - Range: add a row if the constructor intersects the pattern.
2312
- if constructor. is_range_and_should_match_exhaustively ( cx . tcx ) {
2300
+ if constructor. is_integral_range ( ) {
2313
2301
match (
2314
2302
IntRange :: from_ctor ( cx. tcx , cx. param_env , constructor) ,
2315
2303
IntRange :: from_pat ( cx. tcx , cx. param_env , pat) ,
2316
2304
) {
2317
- ( Some ( ctor) , Some ( pat) ) => ctor. intersection ( & pat) . map ( |_| {
2305
+ ( Some ( ctor) , Some ( pat) ) => ctor. intersection ( cx . tcx , & pat) . map ( |_| {
2318
2306
// Constructor splitting should ensure that all intersections we encounter
2319
2307
// are actually inclusions.
2320
2308
let ( pat_lo, pat_hi) = pat. range . into_inner ( ) ;
@@ -2324,16 +2312,6 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
2324
2312
} ) ,
2325
2313
_ => None ,
2326
2314
}
2327
- } else if constructor. is_integral_range ( ) {
2328
- // If we have an integer range that should not be matched exhaustively, fallback to
2329
- // checking for inclusion.
2330
- match (
2331
- IntRange :: from_ctor ( cx. tcx , cx. param_env , constructor) ,
2332
- IntRange :: from_pat ( cx. tcx , cx. param_env , pat) ,
2333
- ) {
2334
- ( Some ( ctor) , Some ( pat) ) if ctor. is_subrange ( & pat) => Some ( PatStack :: default ( ) ) ,
2335
- _ => None ,
2336
- }
2337
2315
} else {
2338
2316
// Fallback for non-ranges and ranges that involve
2339
2317
// floating-point numbers, which are not conveniently handled
0 commit comments