Skip to content

Commit 42220f0

Browse files
committed
ScalarInt: add methods to assert being a (u)int of given size
1 parent 5e6184c commit 42220f0

File tree

13 files changed

+78
-72
lines changed

13 files changed

+78
-72
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+19-22
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub(crate) fn codegen_const_value<'tcx>(
110110
if fx.clif_type(layout.ty).is_some() {
111111
return CValue::const_val(fx, layout, int);
112112
} else {
113-
let raw_val = int.size().truncate(int.to_bits(int.size()).unwrap());
113+
let raw_val = int.size().truncate(int.assert_bits(int.size()));
114114
let val = match int.size().bytes() {
115115
1 => fx.bcx.ins().iconst(types::I8, raw_val as i64),
116116
2 => fx.bcx.ins().iconst(types::I16, raw_val as i64),
@@ -491,27 +491,24 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
491491
return None;
492492
}
493493
let scalar_int = mir_operand_get_const_val(fx, operand)?;
494-
let scalar_int = match fx
495-
.layout_of(*ty)
496-
.size
497-
.cmp(&scalar_int.size())
498-
{
499-
Ordering::Equal => scalar_int,
500-
Ordering::Less => match ty.kind() {
501-
ty::Uint(_) => ScalarInt::try_from_uint(
502-
scalar_int.try_to_uint(scalar_int.size()).unwrap(),
503-
fx.layout_of(*ty).size,
504-
)
505-
.unwrap(),
506-
ty::Int(_) => ScalarInt::try_from_int(
507-
scalar_int.try_to_int(scalar_int.size()).unwrap(),
508-
fx.layout_of(*ty).size,
509-
)
510-
.unwrap(),
511-
_ => unreachable!(),
512-
},
513-
Ordering::Greater => return None,
514-
};
494+
let scalar_int =
495+
match fx.layout_of(*ty).size.cmp(&scalar_int.size()) {
496+
Ordering::Equal => scalar_int,
497+
Ordering::Less => match ty.kind() {
498+
ty::Uint(_) => ScalarInt::try_from_uint(
499+
scalar_int.assert_uint(scalar_int.size()),
500+
fx.layout_of(*ty).size,
501+
)
502+
.unwrap(),
503+
ty::Int(_) => ScalarInt::try_from_int(
504+
scalar_int.assert_int(scalar_int.size()),
505+
fx.layout_of(*ty).size,
506+
)
507+
.unwrap(),
508+
_ => unreachable!(),
509+
},
510+
Ordering::Greater => return None,
511+
};
515512
computed_scalar_int = Some(scalar_int);
516513
}
517514
Rvalue::Use(operand) => {

compiler/rustc_codegen_cranelift/src/value_and_place.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ impl<'tcx> CValue<'tcx> {
326326

327327
let val = match layout.ty.kind() {
328328
ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
329-
let const_val = const_val.to_bits(layout.size).unwrap();
329+
let const_val = const_val.assert_bits(layout.size);
330330
let lsb = fx.bcx.ins().iconst(types::I64, const_val as u64 as i64);
331331
let msb = fx.bcx.ins().iconst(types::I64, (const_val >> 64) as u64 as i64);
332332
fx.bcx.ins().iconcat(lsb, msb)
@@ -338,7 +338,7 @@ impl<'tcx> CValue<'tcx> {
338338
| ty::Ref(..)
339339
| ty::RawPtr(..)
340340
| ty::FnPtr(..) => {
341-
let raw_val = const_val.size().truncate(const_val.to_bits(layout.size).unwrap());
341+
let raw_val = const_val.size().truncate(const_val.assert_bits(layout.size));
342342
fx.bcx.ins().iconst(clif_ty, raw_val as i64)
343343
}
344344
ty::Float(FloatTy::F32) => {

compiler/rustc_const_eval/src/interpret/discriminant.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
295295
&niche_start_val,
296296
)?
297297
.to_scalar()
298-
.try_to_int()
299-
.unwrap();
298+
.assert_int();
300299
Ok(Some((tag, tag_field)))
301300
}
302301
}

compiler/rustc_const_eval/src/interpret/operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
249249
}
250250

251251
/// Return the immediate as a `ScalarInt`. Ensures that it has the size that the layout of the
252-
/// immediate indcates.
252+
/// immediate indicates.
253253
#[inline]
254254
pub fn to_scalar_int(&self) -> InterpResult<'tcx, ScalarInt> {
255255
let s = self.to_scalar().to_scalar_int()?;

compiler/rustc_const_eval/src/interpret/operator.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
155155
let l = left.to_scalar_int()?;
156156
let r = right.to_scalar_int()?;
157157
// Prepare to convert the values to signed or unsigned form.
158-
let l_signed = || l.try_to_int(left.layout.size).unwrap();
159-
let l_unsigned = || l.try_to_uint(left.layout.size).unwrap();
160-
let r_signed = || r.try_to_int(right.layout.size).unwrap();
161-
let r_unsigned = || r.try_to_uint(right.layout.size).unwrap();
158+
let l_signed = || l.assert_int(left.layout.size);
159+
let l_unsigned = || l.assert_uint(left.layout.size);
160+
let r_signed = || r.assert_int(right.layout.size);
161+
let r_unsigned = || r.assert_uint(right.layout.size);
162162

163163
let throw_ub_on_overflow = match bin_op {
164164
AddUnchecked => Some(sym::unchecked_add),

compiler/rustc_middle/src/mir/consts.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<'tcx> ConstValue<'tcx> {
8787
}
8888

8989
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
90-
self.try_to_scalar_int()?.to_bits(size).ok()
90+
self.try_to_scalar_int()?.try_to_bits(size).ok()
9191
}
9292

9393
pub fn try_to_bool(&self) -> Option<bool> {
@@ -260,7 +260,7 @@ impl<'tcx> Const<'tcx> {
260260

261261
#[inline]
262262
pub fn try_to_bits(self, size: Size) -> Option<u128> {
263-
self.try_to_scalar_int()?.to_bits(size).ok()
263+
self.try_to_scalar_int()?.try_to_bits(size).ok()
264264
}
265265

266266
#[inline]
@@ -334,7 +334,7 @@ impl<'tcx> Const<'tcx> {
334334
let int = self.try_eval_scalar_int(tcx, param_env)?;
335335
let size =
336336
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
337-
int.to_bits(size).ok()
337+
int.try_to_bits(size).ok()
338338
}
339339

340340
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.

compiler/rustc_middle/src/mir/interpret/value.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ impl<Prov> Scalar<Prov> {
236236
) -> Result<Either<u128, Pointer<Prov>>, ScalarSizeMismatch> {
237237
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
238238
Ok(match self {
239-
Scalar::Int(int) => Left(int.to_bits(target_size).map_err(|size| {
239+
Scalar::Int(int) => Left(int.try_to_bits(target_size).map_err(|size| {
240240
ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes() }
241241
})?),
242242
Scalar::Ptr(ptr, sz) => {
@@ -316,7 +316,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
316316
#[inline]
317317
pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
318318
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
319-
self.to_scalar_int()?.to_bits(target_size).map_err(|size| {
319+
self.to_scalar_int()?.try_to_bits(target_size).map_err(|size| {
320320
err_ub!(ScalarSizeMismatch(ScalarSizeMismatch {
321321
target_size: target_size.bytes(),
322322
data_size: size.bytes(),

compiler/rustc_middle/src/ty/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ impl<'tcx> Const<'tcx> {
406406
let size =
407407
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
408408
// if `ty` does not depend on generic parameters, use an empty param_env
409-
int.to_bits(size).ok()
409+
int.try_to_bits(size).ok()
410410
}
411411

412412
#[inline]

compiler/rustc_middle/src/ty/consts/int.rs

+39-28
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,7 @@ impl ScalarInt {
247247
}
248248

249249
#[inline]
250-
pub fn assert_bits(self, target_size: Size) -> u128 {
251-
self.to_bits(target_size).unwrap_or_else(|size| {
252-
bug!("expected int of size {}, but got size {}", target_size.bytes(), size.bytes())
253-
})
254-
}
255-
256-
#[inline]
257-
pub fn to_bits(self, target_size: Size) -> Result<u128, Size> {
250+
pub fn try_to_bits(self, target_size: Size) -> Result<u128, Size> {
258251
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
259252
if target_size.bytes() == u64::from(self.size.get()) {
260253
self.check_data();
@@ -264,48 +257,60 @@ impl ScalarInt {
264257
}
265258
}
266259

260+
#[inline]
261+
pub fn assert_bits(self, target_size: Size) -> u128 {
262+
self.try_to_bits(target_size).unwrap_or_else(|size| {
263+
bug!("expected int of size {}, but got size {}", target_size.bytes(), size.bytes())
264+
})
265+
}
266+
267267
/// Tries to convert the `ScalarInt` to an unsigned integer of the given size.
268268
/// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
269269
/// `ScalarInt`s size in that case.
270270
#[inline]
271271
pub fn try_to_uint(self, size: Size) -> Result<u128, Size> {
272-
self.to_bits(size)
272+
self.try_to_bits(size)
273+
}
274+
275+
#[inline]
276+
pub fn assert_uint(self, size: Size) -> u128 {
277+
self.assert_bits(size)
273278
}
274279

275280
// Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt`
276-
// in not equal to `Size { raw: 1 }` and returns the `size` value of the `ScalarInt` in
281+
// in not equal to 1 byte and returns the `size` value of the `ScalarInt` in
277282
// that case.
278283
#[inline]
279284
pub fn try_to_u8(self) -> Result<u8, Size> {
280285
self.try_to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
281286
}
282287

283288
/// Tries to convert the `ScalarInt` to `u16`. Fails if the size of the `ScalarInt`
284-
/// in not equal to `Size { raw: 2 }` and returns the `size` value of the `ScalarInt` in
289+
/// in not equal to 2 bytes and returns the `size` value of the `ScalarInt` in
285290
/// that case.
286291
#[inline]
287292
pub fn try_to_u16(self) -> Result<u16, Size> {
288293
self.try_to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
289294
}
290295

291296
/// Tries to convert the `ScalarInt` to `u32`. Fails if the `size` of the `ScalarInt`
292-
/// in not equal to `Size { raw: 4 }` and returns the `size` value of the `ScalarInt` in
297+
/// in not equal to 4 bytes and returns the `size` value of the `ScalarInt` in
293298
/// that case.
294299
#[inline]
295300
pub fn try_to_u32(self) -> Result<u32, Size> {
296301
self.try_to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
297302
}
298303

299304
/// Tries to convert the `ScalarInt` to `u64`. Fails if the `size` of the `ScalarInt`
300-
/// in not equal to `Size { raw: 8 }` and returns the `size` value of the `ScalarInt` in
305+
/// in not equal to 8 bytes and returns the `size` value of the `ScalarInt` in
301306
/// that case.
302307
#[inline]
303308
pub fn try_to_u64(self) -> Result<u64, Size> {
304309
self.try_to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
305310
}
306311

307312
/// Tries to convert the `ScalarInt` to `u128`. Fails if the `size` of the `ScalarInt`
308-
/// in not equal to `Size { raw: 16 }` and returns the `size` value of the `ScalarInt` in
313+
/// in not equal to 16 bytes and returns the `size` value of the `ScalarInt` in
309314
/// that case.
310315
#[inline]
311316
pub fn try_to_u128(self) -> Result<u128, Size> {
@@ -318,7 +323,7 @@ impl ScalarInt {
318323
}
319324

320325
// Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
321-
// in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size`
326+
// in not equal to 1 byte or if the value is not 0 or 1 and returns the `size`
322327
// value of the `ScalarInt` in that case.
323328
#[inline]
324329
pub fn try_to_bool(self) -> Result<bool, Size> {
@@ -334,40 +339,46 @@ impl ScalarInt {
334339
/// `ScalarInt`s size in that case.
335340
#[inline]
336341
pub fn try_to_int(self, size: Size) -> Result<i128, Size> {
337-
let b = self.to_bits(size)?;
342+
let b = self.try_to_bits(size)?;
338343
Ok(size.sign_extend(b) as i128)
339344
}
340345

346+
#[inline]
347+
pub fn assert_int(self, size: Size) -> i128 {
348+
let b = self.assert_bits(size);
349+
size.sign_extend(b) as i128
350+
}
351+
341352
/// Tries to convert the `ScalarInt` to i8.
342-
/// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 1 }`
353+
/// Fails if the size of the `ScalarInt` is not equal to 1 byte
343354
/// and returns the `ScalarInt`s size in that case.
344355
pub fn try_to_i8(self) -> Result<i8, Size> {
345356
self.try_to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap())
346357
}
347358

348359
/// Tries to convert the `ScalarInt` to i16.
349-
/// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 2 }`
360+
/// Fails if the size of the `ScalarInt` is not equal to 2 bytes
350361
/// and returns the `ScalarInt`s size in that case.
351362
pub fn try_to_i16(self) -> Result<i16, Size> {
352363
self.try_to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap())
353364
}
354365

355366
/// Tries to convert the `ScalarInt` to i32.
356-
/// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 4 }`
367+
/// Fails if the size of the `ScalarInt` is not equal to 4 bytes
357368
/// and returns the `ScalarInt`s size in that case.
358369
pub fn try_to_i32(self) -> Result<i32, Size> {
359370
self.try_to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap())
360371
}
361372

362373
/// Tries to convert the `ScalarInt` to i64.
363-
/// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 8 }`
374+
/// Fails if the size of the `ScalarInt` is not equal to 8 bytes
364375
/// and returns the `ScalarInt`s size in that case.
365376
pub fn try_to_i64(self) -> Result<i64, Size> {
366377
self.try_to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap())
367378
}
368379

369380
/// Tries to convert the `ScalarInt` to i128.
370-
/// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 16 }`
381+
/// Fails if the size of the `ScalarInt` is not equal to 16 bytes
371382
/// and returns the `ScalarInt`s size in that case.
372383
pub fn try_to_i128(self) -> Result<i128, Size> {
373384
self.try_to_int(Size::from_bits(128))
@@ -381,7 +392,7 @@ impl ScalarInt {
381392
#[inline]
382393
pub fn try_to_float<F: Float>(self) -> Result<F, Size> {
383394
// Going through `to_uint` to check size and truncation.
384-
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
395+
Ok(F::from_bits(self.try_to_bits(Size::from_bits(F::BITS))?))
385396
}
386397

387398
#[inline]
@@ -430,7 +441,7 @@ macro_rules! try_from {
430441
fn try_from(int: ScalarInt) -> Result<Self, Size> {
431442
// The `unwrap` cannot fail because to_bits (if it succeeds)
432443
// is guaranteed to return a value that fits into the size.
433-
int.to_bits(Size::from_bytes(std::mem::size_of::<$ty>()))
444+
int.try_to_bits(Size::from_bytes(std::mem::size_of::<$ty>()))
434445
.map(|u| u.try_into().unwrap())
435446
}
436447
}
@@ -465,7 +476,7 @@ impl TryFrom<ScalarInt> for char {
465476

466477
#[inline]
467478
fn try_from(int: ScalarInt) -> Result<Self, Self::Error> {
468-
let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else {
479+
let Ok(bits) = int.try_to_bits(Size::from_bytes(std::mem::size_of::<char>())) else {
469480
return Err(CharTryFromScalarInt);
470481
};
471482
match char::from_u32(bits.try_into().unwrap()) {
@@ -487,7 +498,7 @@ impl TryFrom<ScalarInt> for Half {
487498
type Error = Size;
488499
#[inline]
489500
fn try_from(int: ScalarInt) -> Result<Self, Size> {
490-
int.to_bits(Size::from_bytes(2)).map(Self::from_bits)
501+
int.try_to_bits(Size::from_bytes(2)).map(Self::from_bits)
491502
}
492503
}
493504

@@ -503,7 +514,7 @@ impl TryFrom<ScalarInt> for Single {
503514
type Error = Size;
504515
#[inline]
505516
fn try_from(int: ScalarInt) -> Result<Self, Size> {
506-
int.to_bits(Size::from_bytes(4)).map(Self::from_bits)
517+
int.try_to_bits(Size::from_bytes(4)).map(Self::from_bits)
507518
}
508519
}
509520

@@ -519,7 +530,7 @@ impl TryFrom<ScalarInt> for Double {
519530
type Error = Size;
520531
#[inline]
521532
fn try_from(int: ScalarInt) -> Result<Self, Size> {
522-
int.to_bits(Size::from_bytes(8)).map(Self::from_bits)
533+
int.try_to_bits(Size::from_bytes(8)).map(Self::from_bits)
523534
}
524535
}
525536

@@ -535,7 +546,7 @@ impl TryFrom<ScalarInt> for Quad {
535546
type Error = Size;
536547
#[inline]
537548
fn try_from(int: ScalarInt) -> Result<Self, Size> {
538-
int.to_bits(Size::from_bytes(16)).map(Self::from_bits)
549+
int.try_to_bits(Size::from_bytes(16)).map(Self::from_bits)
539550
}
540551
}
541552

compiler/rustc_mir_transform/src/known_panics_lint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
796796
if let Some(ref value) = self.eval_operand(discr)
797797
&& let Some(value_const) = self.use_ecx(|this| this.ecx.read_scalar(value))
798798
&& let Ok(constant) = value_const.try_to_int()
799-
&& let Ok(constant) = constant.to_bits(constant.size())
799+
&& let Ok(constant) = constant.try_to_bits(constant.size())
800800
{
801801
// We managed to evaluate the discriminant, so we know we only need to visit
802802
// one target.

compiler/rustc_mir_transform/src/match_branches.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
369369
}
370370

371371
fn int_equal(l: ScalarInt, r: impl Into<u128>, size: Size) -> bool {
372-
l.try_to_int(l.size()).unwrap()
373-
== ScalarInt::try_from_uint(r, size).unwrap().try_to_int(size).unwrap()
372+
l.assert_int(l.size()) == ScalarInt::try_from_uint(r, size).unwrap().assert_int(size)
374373
}
375374

376375
// We first compare the two branches, and then the other branches need to fulfill the same conditions.

0 commit comments

Comments
 (0)