[−][src]Struct rustc_mir_build::thir::pattern::_match::IntRange

pub(in thir::pattern::_match) struct IntRange<'tcx> {
    range: RangeInclusive<u128>,
    ty: Ty<'tcx>,
    span: Span,
}

An inclusive interval, used for precise integer exhaustiveness checking. IntRanges always store a contiguous range. This means that values are encoded such that 0 encodes the minimum value for the integer, regardless of the signedness. For example, the pattern -128..=127i8 is encoded as 0..=255. This makes comparisons and arithmetic on interval endpoints much more straightforward. See signed_bias for details.

IntRange is never used to encode an empty range or a "range" that wraps around the (offset) space: i.e., range.lo <= range.hi.

Fields

range: RangeInclusive<u128>ty: Ty<'tcx>span: Span

Implementations

impl<'tcx> IntRange<'tcx>[src]

pub(in thir::pattern::_match) fn is_integral(
    ty: Ty<'_>
) -> bool
[src]

pub(in thir::pattern::_match) fn is_singleton(
    &self
) -> bool
[src]

pub(in thir::pattern::_match) fn boundaries(
    &self
) -> (u128, u128)
[src]

pub(in thir::pattern::_match) fn treat_exhaustively(
    &self,
    tcx: TyCtxt<'tcx>
) -> bool
[src]

Don't treat usize/isize exhaustively unless the precise_pointer_size_matching feature is enabled.

pub(in thir::pattern::_match) fn integral_size_and_signed_bias(
    tcx: TyCtxt<'tcx>,
    ty: Ty<'_>
) -> Option<(Size, u128)>
[src]

pub(in thir::pattern::_match) fn from_const(
    tcx: TyCtxt<'tcx>,
    param_env: ParamEnv<'tcx>,
    value: &Const<'tcx>,
    span: Span
) -> Option<IntRange<'tcx>>
[src]

pub(in thir::pattern::_match) fn from_range(
    tcx: TyCtxt<'tcx>,
    lo: u128,
    hi: u128,
    ty: Ty<'tcx>,
    end: &RangeEnd,
    span: Span
) -> Option<IntRange<'tcx>>
[src]

pub(in thir::pattern::_match) fn signed_bias(
    tcx: TyCtxt<'tcx>,
    ty: Ty<'tcx>
) -> u128
[src]

pub(in thir::pattern::_match) fn is_subrange(
    &self,
    other: &Self
) -> bool
[src]

pub(in thir::pattern::_match) fn intersection(
    &self,
    tcx: TyCtxt<'tcx>,
    other: &Self
) -> Option<Self>
[src]

pub(in thir::pattern::_match) fn suspicious_intersection(
    &self,
    other: &Self
) -> bool
[src]

pub(in thir::pattern::_match) fn to_pat(
    &self,
    tcx: TyCtxt<'tcx>
) -> Pat<'tcx>
[src]

pub(in thir::pattern::_match) fn split<'p>(
    &self,
    pcx: PatCtxt<'_, 'p, 'tcx>,
    hir_id: Option<HirId>
) -> SmallVec<[Constructor<'tcx>; 1]>
[src]

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 U(S(c, P), S(c, p)) 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.)

pub(in thir::pattern::_match) fn lint_overlapping_patterns(
    &self,
    tcx: TyCtxt<'tcx>,
    hir_id: Option<HirId>,
    ty: Ty<'tcx>,
    overlaps: Vec<IntRange<'tcx>>
)
[src]

pub(in thir::pattern::_match) fn is_covered_by<'p>(
    &self,
    pcx: PatCtxt<'_, 'p, 'tcx>,
    other: &Self
) -> bool
[src]

See Constructor::is_covered_by

Trait Implementations

impl<'tcx> Clone for IntRange<'tcx>[src]

impl<'tcx> Debug for IntRange<'tcx>[src]

impl<'tcx> PartialEq<IntRange<'tcx>> for IntRange<'tcx>[src]

Ignore spans when comparing, they don't carry semantic information as they are only for lints.

Auto Trait Implementations

impl<'tcx> !RefUnwindSafe for IntRange<'tcx>

impl<'tcx> !Send for IntRange<'tcx>

impl<'tcx> !Sync for IntRange<'tcx>

impl<'tcx> Unpin for IntRange<'tcx>

impl<'tcx> !UnwindSafe for IntRange<'tcx>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized, 
[src]

impl<T> Borrow<T> for T where
    T: ?Sized, 
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized, 
[src]

impl<'a, T> Captures<'a> for T where
    T: ?Sized, 
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone, 
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.