Make MaybeInfiniteInt
rustc-independent
This commit is contained in:
parent
24adca0a26
commit
de3f983bcd
@ -159,9 +159,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||||||
use rustc_hir::RangeEnd;
|
use rustc_hir::RangeEnd;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::mir::Const;
|
use rustc_middle::mir::Const;
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_target::abi::VariantIdx;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
|
||||||
use rustc_target::abi::{Integer, VariantIdx};
|
|
||||||
|
|
||||||
use self::Constructor::*;
|
use self::Constructor::*;
|
||||||
use self::MaybeInfiniteInt::*;
|
use self::MaybeInfiniteInt::*;
|
||||||
@ -183,6 +181,7 @@ enum Presence {
|
|||||||
pub enum MaybeInfiniteInt {
|
pub enum MaybeInfiniteInt {
|
||||||
NegInfinity,
|
NegInfinity,
|
||||||
/// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite`.
|
/// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite`.
|
||||||
|
#[non_exhaustive]
|
||||||
Finite(u128),
|
Finite(u128),
|
||||||
/// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range.
|
/// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range.
|
||||||
JustAfterMax,
|
JustAfterMax,
|
||||||
@ -190,23 +189,31 @@ pub enum MaybeInfiniteInt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MaybeInfiniteInt {
|
impl MaybeInfiniteInt {
|
||||||
// The return value of `signed_bias` should be XORed with a value to encode/decode it.
|
pub fn new_finite_uint(bits: u128) -> Self {
|
||||||
pub(crate) fn signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> u128 {
|
Finite(bits)
|
||||||
match *ty.kind() {
|
|
||||||
ty::Int(ity) => {
|
|
||||||
let bits = Integer::from_int_ty(&tcx, ity).size().bits() as u128;
|
|
||||||
1u128 << (bits - 1)
|
|
||||||
}
|
|
||||||
_ => 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pub fn new_finite_int(bits: u128, size: u64) -> Self {
|
||||||
pub fn new_finite(tcx: TyCtxt<'_>, ty: Ty<'_>, bits: u128) -> Self {
|
|
||||||
let bias = Self::signed_bias(tcx, ty);
|
|
||||||
// Perform a shift if the underlying types are signed, which makes the interval arithmetic
|
// Perform a shift if the underlying types are signed, which makes the interval arithmetic
|
||||||
// type-independent.
|
// type-independent.
|
||||||
let x = bits ^ bias;
|
let bias = 1u128 << (size - 1);
|
||||||
Finite(x)
|
Finite(bits ^ bias)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_finite_uint(self) -> Option<u128> {
|
||||||
|
match self {
|
||||||
|
Finite(bits) => Some(bits),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn as_finite_int(self, size: u64) -> Option<u128> {
|
||||||
|
// We decode the shift.
|
||||||
|
match self {
|
||||||
|
Finite(bits) => {
|
||||||
|
let bias = 1u128 << (size - 1);
|
||||||
|
Some(bits ^ bias)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Note: this will not turn a finite value into an infinite one or vice-versa.
|
/// Note: this will not turn a finite value into an infinite one or vice-versa.
|
||||||
@ -253,8 +260,7 @@ impl IntRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bits<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, bits: u128) -> IntRange {
|
pub fn from_singleton(x: MaybeInfiniteInt) -> IntRange {
|
||||||
let x = MaybeInfiniteInt::new_finite(tcx, ty, bits);
|
|
||||||
IntRange { lo: x, hi: x.plus_one() }
|
IntRange { lo: x, hi: x.plus_one() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,10 +204,10 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
|
|||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub fn ctors_for_ty(&self, ty: Ty<'tcx>) -> ConstructorSet {
|
pub fn ctors_for_ty(&self, ty: Ty<'tcx>) -> ConstructorSet {
|
||||||
let cx = self;
|
let cx = self;
|
||||||
let make_range = |start, end| {
|
let make_uint_range = |start, end| {
|
||||||
IntRange::from_range(
|
IntRange::from_range(
|
||||||
MaybeInfiniteInt::new_finite(cx.tcx, ty, start),
|
MaybeInfiniteInt::new_finite_uint(start),
|
||||||
MaybeInfiniteInt::new_finite(cx.tcx, ty, end),
|
MaybeInfiniteInt::new_finite_uint(end),
|
||||||
RangeEnd::Included,
|
RangeEnd::Included,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -218,8 +218,8 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
|
|||||||
ty::Char => {
|
ty::Char => {
|
||||||
// The valid Unicode Scalar Value ranges.
|
// The valid Unicode Scalar Value ranges.
|
||||||
ConstructorSet::Integers {
|
ConstructorSet::Integers {
|
||||||
range_1: make_range('\u{0000}' as u128, '\u{D7FF}' as u128),
|
range_1: make_uint_range('\u{0000}' as u128, '\u{D7FF}' as u128),
|
||||||
range_2: Some(make_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
|
range_2: Some(make_uint_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&ty::Int(ity) => {
|
&ty::Int(ity) => {
|
||||||
@ -230,22 +230,24 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
|
|||||||
hi: MaybeInfiniteInt::PosInfinity,
|
hi: MaybeInfiniteInt::PosInfinity,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let bits = Integer::from_int_ty(&cx.tcx, ity).size().bits() as u128;
|
let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
|
||||||
let min = 1u128 << (bits - 1);
|
let min = 1u128 << (size - 1);
|
||||||
let max = min - 1;
|
let max = min - 1;
|
||||||
make_range(min, max)
|
let min = MaybeInfiniteInt::new_finite_int(min, size);
|
||||||
|
let max = MaybeInfiniteInt::new_finite_int(max, size);
|
||||||
|
IntRange::from_range(min, max, RangeEnd::Included)
|
||||||
};
|
};
|
||||||
ConstructorSet::Integers { range_1: range, range_2: None }
|
ConstructorSet::Integers { range_1: range, range_2: None }
|
||||||
}
|
}
|
||||||
&ty::Uint(uty) => {
|
&ty::Uint(uty) => {
|
||||||
let range = if ty.is_ptr_sized_integral() {
|
let range = if ty.is_ptr_sized_integral() {
|
||||||
// The max value of `usize` is not allowed to be observed.
|
// The max value of `usize` is not allowed to be observed.
|
||||||
let lo = MaybeInfiniteInt::new_finite(cx.tcx, ty, 0);
|
let lo = MaybeInfiniteInt::new_finite_uint(0);
|
||||||
IntRange { lo, hi: MaybeInfiniteInt::PosInfinity }
|
IntRange { lo, hi: MaybeInfiniteInt::PosInfinity }
|
||||||
} else {
|
} else {
|
||||||
let size = Integer::from_uint_ty(&cx.tcx, uty).size();
|
let size = Integer::from_uint_ty(&cx.tcx, uty).size();
|
||||||
let max = size.truncate(u128::MAX);
|
let max = size.truncate(u128::MAX);
|
||||||
make_range(0, max)
|
make_uint_range(0, max)
|
||||||
};
|
};
|
||||||
ConstructorSet::Integers { range_1: range, range_2: None }
|
ConstructorSet::Integers { range_1: range, range_2: None }
|
||||||
}
|
}
|
||||||
@ -329,7 +331,13 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
|
|||||||
PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
|
PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
|
||||||
PatRangeBoundary::Finite(value) => {
|
PatRangeBoundary::Finite(value) => {
|
||||||
let bits = value.eval_bits(self.tcx, self.param_env);
|
let bits = value.eval_bits(self.tcx, self.param_env);
|
||||||
MaybeInfiniteInt::new_finite(self.tcx, ty, bits)
|
match *ty.kind() {
|
||||||
|
ty::Int(ity) => {
|
||||||
|
let size = Integer::from_int_ty(&self.tcx, ity).size().bits();
|
||||||
|
MaybeInfiniteInt::new_finite_int(bits, size)
|
||||||
|
}
|
||||||
|
_ => MaybeInfiniteInt::new_finite_uint(bits),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PatRangeBoundary::PosInfinity => MaybeInfiniteInt::PosInfinity,
|
PatRangeBoundary::PosInfinity => MaybeInfiniteInt::PosInfinity,
|
||||||
}
|
}
|
||||||
@ -428,7 +436,16 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
|
|||||||
}
|
}
|
||||||
ty::Char | ty::Int(_) | ty::Uint(_) => {
|
ty::Char | ty::Int(_) | ty::Uint(_) => {
|
||||||
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
|
||||||
Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)),
|
Some(bits) => {
|
||||||
|
let x = match *pat.ty.kind() {
|
||||||
|
ty::Int(ity) => {
|
||||||
|
let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
|
||||||
|
MaybeInfiniteInt::new_finite_int(bits, size)
|
||||||
|
}
|
||||||
|
_ => MaybeInfiniteInt::new_finite_uint(bits),
|
||||||
|
};
|
||||||
|
IntRange(IntRange::from_singleton(x))
|
||||||
|
}
|
||||||
None => Opaque(OpaqueId::new()),
|
None => Opaque(OpaqueId::new()),
|
||||||
};
|
};
|
||||||
fields = &[];
|
fields = &[];
|
||||||
@ -559,10 +576,12 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
|
|||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
match miint {
|
match miint {
|
||||||
NegInfinity => PatRangeBoundary::NegInfinity,
|
NegInfinity => PatRangeBoundary::NegInfinity,
|
||||||
Finite(x) => {
|
Finite(_) => {
|
||||||
let bias = MaybeInfiniteInt::signed_bias(tcx, ty);
|
|
||||||
let bits = x ^ bias;
|
|
||||||
let size = ty.primitive_size(tcx);
|
let size = ty.primitive_size(tcx);
|
||||||
|
let bits = match *ty.kind() {
|
||||||
|
ty::Int(_) => miint.as_finite_int(size.bits()).unwrap(),
|
||||||
|
_ => miint.as_finite_uint().unwrap(),
|
||||||
|
};
|
||||||
match Scalar::try_from_uint(bits, size) {
|
match Scalar::try_from_uint(bits, size) {
|
||||||
Some(scalar) => {
|
Some(scalar) => {
|
||||||
let value = mir::Const::from_scalar(tcx, scalar, ty);
|
let value = mir::Const::from_scalar(tcx, scalar, ty);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user