From ae77f4b6dbea62b97cd86273a7c9714b07c02fd5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 21 Aug 2026 13:49:32 +0200 Subject: [PATCH] try to reduce impact of scalar size checks --- .../rustc_middle/src/mir/interpret/value.rs | 32 +++++++++++-------- compiler/rustc_middle/src/ty/consts/int.rs | 20 ++++++------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 56cded69e469e..e78b000a84c0f 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::num::NonZero; use either::{Either, Left, Right}; use rustc_abi::{HasDataLayout, Size}; @@ -29,7 +30,7 @@ pub enum Scalar { /// We also store the size of the pointer, such that a `Scalar` always knows how big it is. /// The size is always the pointer size of the current target, but this is not information /// that we always have readily available. - Ptr(Pointer, u8), + Ptr(Pointer, NonZero), } #[cfg(target_pointer_width = "64")] @@ -102,7 +103,8 @@ impl From for Scalar { impl Scalar { #[inline(always)] pub fn from_pointer(ptr: Pointer, cx: &impl HasDataLayout) -> Self { - Scalar::Ptr(ptr, u8::try_from(cx.pointer_size().bytes()).unwrap()) + let ptr_size = u8::try_from(cx.pointer_size().bytes()).ok().and_then(NonZero::new).unwrap(); + Scalar::Ptr(ptr, ptr_size) } /// Create a Scalar from a pointer with an `Option<_>` provenance (where `None` represents a @@ -236,17 +238,20 @@ impl Scalar { /// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in /// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type. #[inline] - pub fn to_bits_or_ptr_internal(self, target_size: Size) -> Either> { - assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); + pub fn to_bits_or_ptr_internal(self, expected_size: Size) -> Either> { match self { - Scalar::Int(int) => Left(int.to_bits(target_size)), + Scalar::Int(int) => Left(int.to_bits(expected_size)), Scalar::Ptr(ptr, sz) => { - assert_eq!( - target_size.bytes(), - u64::from(sz), - "Scalar is a pointer but expected size {}", - target_size.bytes() - ); + let self_size = u64::from(sz.get()); + if expected_size.bytes() != self_size { + #[cold] + fn invalid(expected_size: u64, self_size: u64) -> ! { + panic!("Scalar pointer has size {self_size} but expected {expected_size}") + } + + invalid(expected_size.bytes(), self_size) + } + Right(ptr) } } @@ -256,7 +261,7 @@ impl Scalar { pub fn size(self) -> Size { match self { Scalar::Int(int) => int.size(), - Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz), + Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz.get()), } } } @@ -287,7 +292,8 @@ impl<'tcx, Prov: Provenance> Scalar { Scalar::Int(int) => Ok(int), Scalar::Ptr(ptr, sz) => { if Prov::OFFSET_IS_ADDR { - Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap()) + Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz.get())) + .unwrap()) } else { // We know `offset` is relative, since `OFFSET_IS_ADDR == false`. let (prov, offset) = ptr.into_raw_parts(); diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index ce5ffefe2d4f5..9fa4f157ebffa 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -262,15 +262,17 @@ impl ScalarInt { /// Convert this ScalarInt to the underlying bits. #[inline] - pub fn to_bits(self, target_size: Size) -> u128 { - assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); - assert_eq!( - target_size.bytes(), - u64::from(self.size.get()), - "ScalarInt has size {} but expected {}", - self.size, - target_size.bytes(), - ); + pub fn to_bits(self, expected_size: Size) -> u128 { + let self_size = u64::from(self.size.get()); + if expected_size.bytes() != self_size { + #[cold] + fn invalid(expected_size: u64, self_size: u64) -> ! { + panic!("ScalarInt has size {self_size} but expected {expected_size}") + } + + invalid(expected_size.bytes(), self_size); + } + self.check_data(); self.data }