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