diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index c13307aa419..249273c3595 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -46,7 +46,6 @@ use std::cell::Cell; 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, + pub(crate) lo: u128, + pub(crate) hi: u128, } impl IntRange { @@ -114,20 +114,16 @@ impl IntRange { } 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 @@ impl IntRange { 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 @@ impl IntRange { } 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 { - 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 @@ impl IntRange { 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 @@ impl IntRange { 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 @@ impl IntRange { /// 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}") diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 25e0f3ceaa4..4b314535c89 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -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); }