@@ -1396,9 +1396,9 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Construct
1396
1396
/// impractical. However, observe that for some ranges of integers, the specialisation will be
1397
1397
/// identical across all values in that range (i.e. there are equivalence classes of ranges of
1398
1398
/// constructors based on their `is_useful_specialised` outcome). These classes are grouped by
1399
- /// the patterns that apply to them (both in the matrix `P` and in the new row `p_{m + 1}`). We
1400
- /// can split the range whenever the patterns that apply to that range (specifically: the patterns
1401
- /// that *intersect* with that range) change.
1399
+ /// the patterns that apply to them (in the matrix `P`). We can split the range whenever the
1400
+ /// patterns that apply to that range (specifically: the patterns that *intersect* with that range)
1401
+ /// change.
1402
1402
/// Our solution, therefore, is to split the range constructor into subranges at every single point
1403
1403
/// the group of intersecting patterns changes, which we can compute by converting each pattern to
1404
1404
/// a range and recording its endpoints, then creating subranges between each consecutive pair of
@@ -1407,6 +1407,21 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'_, 'tcx, 'tcx>, ctor: &Construct
1407
1407
/// on actual integers. The nice thing about this is that the number of subranges is linear in the
1408
1408
/// number of rows in the matrix (i.e. the number of cases in the `match` statement), so we don't
1409
1409
/// need to be worried about matching over gargantuan ranges.
1410
+ ///
1411
+ /// Essentially, given the first column of a matrix representing ranges, looking like the following:
1412
+ ///
1413
+ /// |------| |----------| |-------| ||
1414
+ /// |-------| |-------| |----| ||
1415
+ /// |---------|
1416
+ ///
1417
+ /// We truncate the ranges so that they lie inside each range constructor and then split them
1418
+ /// up into equivalence classes so the ranges are no longer overlapping:
1419
+ ///
1420
+ /// |--|--|||-||||--||---|||-------| |-|||| ||
1421
+ ///
1422
+ /// The logic for determining how to split the ranges is a little involved: we need to make sure
1423
+ /// that we have a new range for each subrange for which a different set of rows coïncides, but
1424
+ /// essentially reduces to case analysis on the endpoints of the ranges.
1410
1425
fn split_grouped_constructors < ' p , ' a : ' p , ' tcx : ' a > (
1411
1426
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1412
1427
ctors : Vec < Constructor < ' tcx > > ,
@@ -1420,10 +1435,9 @@ fn split_grouped_constructors<'p, 'a: 'p, 'tcx: 'a>(
1420
1435
// For now, only ranges may denote groups of "subconstructors", so we only need to
1421
1436
// special-case constant ranges.
1422
1437
ConstantRange ( ..) if should_treat_range_exhaustively ( tcx, & ctor) => {
1423
- // We only care about finding all the subranges within the range of the intersection
1424
- // of the new pattern `p_({m + 1},1)` (here `pat`) and the constructor range.
1425
- // Anything else is irrelevant, because it is guaranteed to result in `NotUseful`,
1426
- // which is the default case anyway, and can be ignored.
1438
+ // We only care about finding all the subranges within the range of the constructor
1439
+ // range. Anything else is irrelevant, because it is guaranteed to result in
1440
+ // `NotUseful`, which is the default case anyway, and can be ignored.
1427
1441
let ctor_range = IntRange :: from_ctor ( tcx, & ctor) . unwrap ( ) ;
1428
1442
1429
1443
// We're going to collect all the endpoints in the new pattern so we can create
@@ -1479,6 +1493,9 @@ fn split_grouped_constructors<'p, 'a: 'p, 'tcx: 'a>(
1479
1493
// sure we're enumerating precisely the correct ranges. Too few and the matching is
1480
1494
// actually incorrect. Too many and our diagnostics are poorer. This involves some
1481
1495
// case analysis.
1496
+ // In essence, we need to ensure that every time the set of row-ranges that are
1497
+ // overlapping changes (as we go through the values covered by the ranges), we split
1498
+ // into a new subrange.
1482
1499
while let Some ( b) = points. next ( ) {
1483
1500
// a < b (strictly)
1484
1501
if let Endpoint :: Both = a. 1 {
@@ -1522,7 +1539,7 @@ fn constructor_intersects_pattern<'p, 'a: 'p, 'tcx: 'a>(
1522
1539
let ( pat_lo, pat_hi) = pat. range . into_inner ( ) ;
1523
1540
let ( ctor_lo, ctor_hi) = ctor. range . into_inner ( ) ;
1524
1541
assert ! ( pat_lo <= ctor_lo && ctor_hi <= pat_hi) ;
1525
- Some ( vec ! [ ] )
1542
+ vec ! [ ]
1526
1543
} )
1527
1544
}
1528
1545
_ => None ,
0 commit comments