Skip to content

Commit de3f983

Browse files
committedDec 11, 2023
Make MaybeInfiniteInt rustc-independent
1 parent 24adca0 commit de3f983

File tree

2 files changed

+59
-34
lines changed

2 files changed

+59
-34
lines changed
 

‎compiler/rustc_pattern_analysis/src/constructor.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,7 @@ use rustc_data_structures::fx::FxHashSet;
159159
use rustc_hir::RangeEnd;
160160
use rustc_index::IndexVec;
161161
use rustc_middle::mir::Const;
162-
use rustc_middle::ty::layout::IntegerExt;
163-
use rustc_middle::ty::{self, Ty, TyCtxt};
164-
use rustc_target::abi::{Integer, VariantIdx};
162+
use rustc_target::abi::VariantIdx;
165163

166164
use self::Constructor::*;
167165
use self::MaybeInfiniteInt::*;
@@ -183,30 +181,39 @@ enum Presence {
183181
pub enum MaybeInfiniteInt {
184182
NegInfinity,
185183
/// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite`.
184+
#[non_exhaustive]
186185
Finite(u128),
187186
/// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range.
188187
JustAfterMax,
189188
PosInfinity,
190189
}
191190

192191
impl MaybeInfiniteInt {
193-
// The return value of `signed_bias` should be XORed with a value to encode/decode it.
194-
pub(crate) fn signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> u128 {
195-
match *ty.kind() {
196-
ty::Int(ity) => {
197-
let bits = Integer::from_int_ty(&tcx, ity).size().bits() as u128;
198-
1u128 << (bits - 1)
199-
}
200-
_ => 0,
201-
}
192+
pub fn new_finite_uint(bits: u128) -> Self {
193+
Finite(bits)
202194
}
203-
204-
pub fn new_finite(tcx: TyCtxt<'_>, ty: Ty<'_>, bits: u128) -> Self {
205-
let bias = Self::signed_bias(tcx, ty);
195+
pub fn new_finite_int(bits: u128, size: u64) -> Self {
206196
// Perform a shift if the underlying types are signed, which makes the interval arithmetic
207197
// type-independent.
208-
let x = bits ^ bias;
209-
Finite(x)
198+
let bias = 1u128 << (size - 1);
199+
Finite(bits ^ bias)
200+
}
201+
202+
pub fn as_finite_uint(self) -> Option<u128> {
203+
match self {
204+
Finite(bits) => Some(bits),
205+
_ => None,
206+
}
207+
}
208+
pub fn as_finite_int(self, size: u64) -> Option<u128> {
209+
// We decode the shift.
210+
match self {
211+
Finite(bits) => {
212+
let bias = 1u128 << (size - 1);
213+
Some(bits ^ bias)
214+
}
215+
_ => None,
216+
}
210217
}
211218

212219
/// Note: this will not turn a finite value into an infinite one or vice-versa.
@@ -253,8 +260,7 @@ impl IntRange {
253260
}
254261

255262
#[inline]
256-
pub fn from_bits<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, bits: u128) -> IntRange {
257-
let x = MaybeInfiniteInt::new_finite(tcx, ty, bits);
263+
pub fn from_singleton(x: MaybeInfiniteInt) -> IntRange {
258264
IntRange { lo: x, hi: x.plus_one() }
259265
}
260266

‎compiler/rustc_pattern_analysis/src/cx.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,10 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
204204
#[instrument(level = "debug", skip(self), ret)]
205205
pub fn ctors_for_ty(&self, ty: Ty<'tcx>) -> ConstructorSet {
206206
let cx = self;
207-
let make_range = |start, end| {
207+
let make_uint_range = |start, end| {
208208
IntRange::from_range(
209-
MaybeInfiniteInt::new_finite(cx.tcx, ty, start),
210-
MaybeInfiniteInt::new_finite(cx.tcx, ty, end),
209+
MaybeInfiniteInt::new_finite_uint(start),
210+
MaybeInfiniteInt::new_finite_uint(end),
211211
RangeEnd::Included,
212212
)
213213
};
@@ -218,8 +218,8 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
218218
ty::Char => {
219219
// The valid Unicode Scalar Value ranges.
220220
ConstructorSet::Integers {
221-
range_1: make_range('\u{0000}' as u128, '\u{D7FF}' as u128),
222-
range_2: Some(make_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
221+
range_1: make_uint_range('\u{0000}' as u128, '\u{D7FF}' as u128),
222+
range_2: Some(make_uint_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
223223
}
224224
}
225225
&ty::Int(ity) => {
@@ -230,22 +230,24 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
230230
hi: MaybeInfiniteInt::PosInfinity,
231231
}
232232
} else {
233-
let bits = Integer::from_int_ty(&cx.tcx, ity).size().bits() as u128;
234-
let min = 1u128 << (bits - 1);
233+
let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
234+
let min = 1u128 << (size - 1);
235235
let max = min - 1;
236-
make_range(min, max)
236+
let min = MaybeInfiniteInt::new_finite_int(min, size);
237+
let max = MaybeInfiniteInt::new_finite_int(max, size);
238+
IntRange::from_range(min, max, RangeEnd::Included)
237239
};
238240
ConstructorSet::Integers { range_1: range, range_2: None }
239241
}
240242
&ty::Uint(uty) => {
241243
let range = if ty.is_ptr_sized_integral() {
242244
// The max value of `usize` is not allowed to be observed.
243-
let lo = MaybeInfiniteInt::new_finite(cx.tcx, ty, 0);
245+
let lo = MaybeInfiniteInt::new_finite_uint(0);
244246
IntRange { lo, hi: MaybeInfiniteInt::PosInfinity }
245247
} else {
246248
let size = Integer::from_uint_ty(&cx.tcx, uty).size();
247249
let max = size.truncate(u128::MAX);
248-
make_range(0, max)
250+
make_uint_range(0, max)
249251
};
250252
ConstructorSet::Integers { range_1: range, range_2: None }
251253
}
@@ -329,7 +331,13 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
329331
PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
330332
PatRangeBoundary::Finite(value) => {
331333
let bits = value.eval_bits(self.tcx, self.param_env);
332-
MaybeInfiniteInt::new_finite(self.tcx, ty, bits)
334+
match *ty.kind() {
335+
ty::Int(ity) => {
336+
let size = Integer::from_int_ty(&self.tcx, ity).size().bits();
337+
MaybeInfiniteInt::new_finite_int(bits, size)
338+
}
339+
_ => MaybeInfiniteInt::new_finite_uint(bits),
340+
}
333341
}
334342
PatRangeBoundary::PosInfinity => MaybeInfiniteInt::PosInfinity,
335343
}
@@ -428,7 +436,16 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
428436
}
429437
ty::Char | ty::Int(_) | ty::Uint(_) => {
430438
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
431-
Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)),
439+
Some(bits) => {
440+
let x = match *pat.ty.kind() {
441+
ty::Int(ity) => {
442+
let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
443+
MaybeInfiniteInt::new_finite_int(bits, size)
444+
}
445+
_ => MaybeInfiniteInt::new_finite_uint(bits),
446+
};
447+
IntRange(IntRange::from_singleton(x))
448+
}
432449
None => Opaque(OpaqueId::new()),
433450
};
434451
fields = &[];
@@ -559,10 +576,12 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
559576
let tcx = self.tcx;
560577
match miint {
561578
NegInfinity => PatRangeBoundary::NegInfinity,
562-
Finite(x) => {
563-
let bias = MaybeInfiniteInt::signed_bias(tcx, ty);
564-
let bits = x ^ bias;
579+
Finite(_) => {
565580
let size = ty.primitive_size(tcx);
581+
let bits = match *ty.kind() {
582+
ty::Int(_) => miint.as_finite_int(size.bits()).unwrap(),
583+
_ => miint.as_finite_uint().unwrap(),
584+
};
566585
match Scalar::try_from_uint(bits, size) {
567586
Some(scalar) => {
568587
let value = mir::Const::from_scalar(tcx, scalar, ty);

0 commit comments

Comments
 (0)
Please sign in to comment.