[][src]Function rustc_mir::hair::pattern::_match::split_grouped_constructors

Important traits for Vec<u8>
fn split_grouped_constructors<'p, 'a: 'p, 'tcx: 'a>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    ctors: Vec<Constructor<'tcx>>,
    Matrix: &Matrix<'p, 'tcx>,
    ty: Ty<'tcx>
) -> Vec<Constructor<'tcx>>
🔬 This is a nightly-only experimental API. (rustc_private)

this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via Cargo.toml instead?

For exhaustive integer matching, some constructors are grouped within other constructors (namely integer typed values are grouped within ranges). However, when specialising these constructors, we want to be specialising for the underlying constructors (the integers), not the groups (the ranges). Thus we need to split the groups up. Splitting them up naïvely would mean creating a separate constructor for every single value in the range, which is clearly impractical. However, observe that for some ranges of integers, the specialisation will be identical across all values in that range (i.e. there are equivalence classes of ranges of constructors based on their is_useful_specialised outcome). These classes are grouped by the patterns that apply to them (in the matrix P). We can split the range whenever the patterns that apply to that range (specifically: the patterns that intersect with that range) change. Our solution, therefore, is to split the range constructor into subranges at every single point the group of intersecting patterns changes (using the method described below). And voilà! We're testing precisely those ranges that we need to, without any exhaustive matching on actual integers. The nice thing about this is that the number of subranges is linear in the number of rows in the matrix (i.e. the number of cases in the match statement), so we don't need to be worried about matching over gargantuan ranges.

Essentially, given the first column of a matrix representing ranges, looking like the following:

------ ---------- -------
---------

We split the ranges up into equivalence classes so the ranges are no longer overlapping:

|--|--|||-||||--||---|||-------| |-|||| ||

The logic for determining how to split the ranges is fairly straightforward: we calculate boundaries for each interval range, sort them, then create constructors for each new interval between every pair of boundary points. (This essentially sums up to performing the intuitive merging operation depicted above.)