Inline RangeInclusive
into IntRange
This commit is contained in:
parent
a5c67f4107
commit
9bc4c378ab
@ -46,7 +46,6 @@
|
||||
use std::cmp::{self, max, min, Ordering};
|
||||
use std::fmt;
|
||||
use std::iter::once;
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
@ -102,9 +101,10 @@ enum Presence {
|
||||
///
|
||||
/// `IntRange` is never used to encode an empty range or a "range" that wraps
|
||||
/// around the (offset) space: i.e., `range.lo <= range.hi`.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) struct IntRange {
|
||||
range: RangeInclusive<u128>,
|
||||
pub(crate) lo: u128,
|
||||
pub(crate) hi: u128,
|
||||
}
|
||||
|
||||
impl IntRange {
|
||||
@ -114,20 +114,16 @@ pub(super) fn is_integral(ty: Ty<'_>) -> bool {
|
||||
}
|
||||
|
||||
pub(super) fn is_singleton(&self) -> bool {
|
||||
self.range.start() == self.range.end()
|
||||
}
|
||||
|
||||
pub(super) fn boundaries(&self) -> (u128, u128) {
|
||||
(*self.range.start(), *self.range.end())
|
||||
self.lo == self.hi
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_bits<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, bits: u128) -> IntRange {
|
||||
let bias = IntRange::signed_bias(tcx, ty);
|
||||
// Perform a shift if the underlying types are signed,
|
||||
// which makes the interval arithmetic simpler.
|
||||
// Perform a shift if the underlying types are signed, which makes the interval arithmetic
|
||||
// type-independent.
|
||||
let val = bits ^ bias;
|
||||
IntRange { range: val..=val }
|
||||
IntRange { lo: val, hi: val }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -138,16 +134,17 @@ fn from_range<'tcx>(
|
||||
ty: Ty<'tcx>,
|
||||
end: RangeEnd,
|
||||
) -> IntRange {
|
||||
// Perform a shift if the underlying types are signed,
|
||||
// which makes the interval arithmetic simpler.
|
||||
// Perform a shift if the underlying types are signed, which makes the interval arithmetic
|
||||
// type-independent.
|
||||
let bias = IntRange::signed_bias(tcx, ty);
|
||||
let (lo, hi) = (lo ^ bias, hi ^ bias);
|
||||
let offset = (end == RangeEnd::Excluded) as u128;
|
||||
if lo > hi || (lo == hi && end == RangeEnd::Excluded) {
|
||||
let hi = hi - offset;
|
||||
if lo > hi {
|
||||
// This should have been caught earlier by E0030.
|
||||
bug!("malformed range pattern: {}..={}", lo, (hi - offset));
|
||||
bug!("malformed range pattern: {lo}..={hi}");
|
||||
}
|
||||
IntRange { range: lo..=(hi - offset) }
|
||||
IntRange { lo, hi }
|
||||
}
|
||||
|
||||
// The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
|
||||
@ -162,14 +159,12 @@ fn signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> u128 {
|
||||
}
|
||||
|
||||
fn is_subrange(&self, other: &Self) -> bool {
|
||||
other.range.start() <= self.range.start() && self.range.end() <= other.range.end()
|
||||
other.lo <= self.lo && self.hi <= other.hi
|
||||
}
|
||||
|
||||
fn intersection(&self, other: &Self) -> Option<Self> {
|
||||
let (lo, hi) = self.boundaries();
|
||||
let (other_lo, other_hi) = other.boundaries();
|
||||
if lo <= other_hi && other_lo <= hi {
|
||||
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi) })
|
||||
if self.lo <= other.hi && other.lo <= self.hi {
|
||||
Some(IntRange { lo: max(self.lo, other.lo), hi: min(self.hi, other.hi) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -216,9 +211,8 @@ enum IntBoundary {
|
||||
|
||||
fn unpack_intrange(range: IntRange) -> [IntBoundary; 2] {
|
||||
use IntBoundary::*;
|
||||
let (lo, hi) = range.boundaries();
|
||||
let lo = JustBefore(lo);
|
||||
let hi = match hi.checked_add(1) {
|
||||
let lo = JustBefore(range.lo);
|
||||
let hi = match range.hi.checked_add(1) {
|
||||
Some(m) => JustBefore(m),
|
||||
None => AfterMax,
|
||||
};
|
||||
@ -264,21 +258,19 @@ enum IntBoundary {
|
||||
use IntBoundary::*;
|
||||
use Presence::*;
|
||||
let presence = if paren_count > 0 { Seen } else { Unseen };
|
||||
let range = match (prev_bdy, bdy) {
|
||||
(JustBefore(n), JustBefore(m)) if n < m => n..=(m - 1),
|
||||
(JustBefore(n), AfterMax) => n..=u128::MAX,
|
||||
let (lo, hi) = match (prev_bdy, bdy) {
|
||||
(JustBefore(n), JustBefore(m)) if n < m => (n, m - 1),
|
||||
(JustBefore(n), AfterMax) => (n, u128::MAX),
|
||||
_ => unreachable!(), // Ruled out by the sorting and filtering we did
|
||||
};
|
||||
(presence, IntRange { range })
|
||||
(presence, IntRange { lo, hi })
|
||||
})
|
||||
}
|
||||
|
||||
/// Only used for displaying the range.
|
||||
pub(super) fn to_pat<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> {
|
||||
let (lo, hi) = self.boundaries();
|
||||
|
||||
let bias = IntRange::signed_bias(tcx, ty);
|
||||
let (lo_bits, hi_bits) = (lo ^ bias, hi ^ bias);
|
||||
let (lo_bits, hi_bits) = (self.lo ^ bias, self.hi ^ bias);
|
||||
|
||||
let env = ty::ParamEnv::empty().and(ty);
|
||||
let lo_const = mir::Const::from_bits(tcx, lo_bits, env);
|
||||
@ -303,7 +295,7 @@ pub(super) fn to_pat<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Pat<'tcx>
|
||||
/// first.
|
||||
impl fmt::Debug for IntRange {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (lo, hi) = self.boundaries();
|
||||
let (lo, hi) = (self.lo, self.hi);
|
||||
write!(f, "{lo}")?;
|
||||
write!(f, "{}", RangeEnd::Included)?;
|
||||
write!(f, "{hi}")
|
||||
|
@ -1031,9 +1031,10 @@ fn lint_overlapping_range_endpoints<'p, 'tcx>(
|
||||
let split_int_ranges = set.present.iter().filter_map(|c| c.as_int_range());
|
||||
for overlap_range in split_int_ranges.clone() {
|
||||
if overlap_range.is_singleton() {
|
||||
let overlap: u128 = overlap_range.boundaries().0;
|
||||
// Spans of ranges that start or end with the overlap.
|
||||
let overlap: u128 = overlap_range.lo;
|
||||
// Ranges that look like `lo..=overlap`.
|
||||
let mut prefixes: SmallVec<[_; 1]> = Default::default();
|
||||
// Ranges that look like `overlap..=hi`.
|
||||
let mut suffixes: SmallVec<[_; 1]> = Default::default();
|
||||
// Iterate on patterns that contained `overlap`.
|
||||
for pat in column.iter() {
|
||||
@ -1043,17 +1044,16 @@ fn lint_overlapping_range_endpoints<'p, 'tcx>(
|
||||
// Don't lint when one of the ranges is a singleton.
|
||||
continue;
|
||||
}
|
||||
let (start, end) = this_range.boundaries();
|
||||
if start == overlap {
|
||||
// `this_range` looks like `overlap..=end`; it overlaps with any ranges that
|
||||
// look like `start..=overlap`.
|
||||
if this_range.lo == overlap {
|
||||
// `this_range` looks like `overlap..=this_range.hi`; it overlaps with any
|
||||
// ranges that look like `lo..=overlap`.
|
||||
if !prefixes.is_empty() {
|
||||
emit_lint(overlap_range, this_span, &prefixes);
|
||||
}
|
||||
suffixes.push(this_span)
|
||||
} else if end == overlap {
|
||||
// `this_range` looks like `start..=overlap`; it overlaps with any ranges
|
||||
// that look like `overlap..=end`.
|
||||
} else if this_range.hi == overlap {
|
||||
// `this_range` looks like `this_range.lo..=overlap`; it overlaps with any
|
||||
// ranges that look like `overlap..=hi`.
|
||||
if !suffixes.is_empty() {
|
||||
emit_lint(overlap_range, this_span, &suffixes);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user