diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index b856d1708abc91fe85fa2643cd9e927ceeb8ae3e..498b2f1b081b3308dd65720a419537a7db89f7dc 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -167,17 +167,18 @@ pub(super) fn op_to_const<'tcx>( }, Immediate::ScalarPair(a, b) => { // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (data, start) = match ecx.scalar_to_ptr(a.check_init().unwrap()).into_parts() { - (Some(alloc_id), offset) => { - (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) - } - (None, _offset) => ( - ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable( - b"" as &[u8], - )), - 0, - ), - }; + let (data, start) = + match ecx.scalar_to_ptr(a.check_init().unwrap()).unwrap().into_parts() { + (Some(alloc_id), offset) => { + (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) + } + (None, _offset) => ( + ecx.tcx.intern_const_alloc( + Allocation::from_bytes_byte_aligned_immutable(b"" as &[u8]), + ), + 0, + ), + }; let len = b.to_machine_usize(ecx).unwrap(); let start = start.try_into().unwrap(); let len: usize = len.try_into().unwrap(); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c44e27fc4a098bfee17adf1c52c14cb7ad2fb371..d57504deeab90594d79bd30d4c7baec4dbbda4a5 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -197,8 +197,8 @@ fn may_leak(self) -> bool { } impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { - fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> bool { - match (a, b) { + fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, bool> { + Ok(match (a, b) { // Comparisons between integers are always known. (Scalar::Int { .. }, Scalar::Int { .. }) => a == b, // Equality with integers can never be known for sure. @@ -207,11 +207,11 @@ fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> bool { // some things (like functions and vtables) do not have stable addresses // so we need to be careful around them (see e.g. #73722). (Scalar::Ptr(..), Scalar::Ptr(..)) => false, - } + }) } - fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> bool { - match (a, b) { + fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, bool> { + Ok(match (a, b) { // Comparisons between integers are always known. (Scalar::Int(_), Scalar::Int(_)) => a != b, // Comparisons of abstract pointers with null pointers are known if the pointer @@ -219,13 +219,13 @@ fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> bool { // Inequality with integers other than null can never be known for sure. (Scalar::Int(int), ptr @ Scalar::Ptr(..)) | (ptr @ Scalar::Ptr(..), Scalar::Int(int)) => { - int.is_null() && !self.scalar_may_be_null(ptr) + int.is_null() && !self.scalar_may_be_null(ptr)? } // FIXME: return `true` for at least some comparisons where we can reliably // determine the result of runtime inequality tests at compile-time. // Examples include comparison of addresses in different static items. (Scalar::Ptr(..), Scalar::Ptr(..)) => false, - } + }) } } @@ -329,9 +329,9 @@ fn call_intrinsic( let a = ecx.read_immediate(&args[0])?.to_scalar()?; let b = ecx.read_immediate(&args[1])?.to_scalar()?; let cmp = if intrinsic_name == sym::ptr_guaranteed_eq { - ecx.guaranteed_eq(a, b) + ecx.guaranteed_eq(a, b)? } else { - ecx.guaranteed_ne(a, b) + ecx.guaranteed_ne(a, b)? }; ecx.write_scalar(Scalar::from_bool(cmp), dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index a244b79ed075406498e591469536ebb92f704b77..3ea3729dbcd17d765c1be73eba98948927cb08c5 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -283,7 +283,7 @@ fn unsize_into_ptr( if let Some(entry_idx) = vptr_entry_idx { let entry_idx = u64::try_from(entry_idx).unwrap(); let (old_data, old_vptr) = val.to_scalar_pair()?; - let old_vptr = self.scalar_to_ptr(old_vptr); + let old_vptr = self.scalar_to_ptr(old_vptr)?; let new_vptr = self .read_new_vtable_after_trait_upcasting_from_vtable(old_vptr, entry_idx)?; self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index a2ea0f516bfa4dccda68c163bd66b9048d667d1d..f0fff602fe4cfbf8a647c415035898a04eaa8e6f 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -640,7 +640,7 @@ pub(super) fn size_and_align_of( Ok(Some((size, align))) } ty::Dynamic(..) => { - let vtable = self.scalar_to_ptr(metadata.unwrap_meta()); + let vtable = self.scalar_to_ptr(metadata.unwrap_meta())?; // Read size and align from vtable (already checks size). Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index f1acb9e41c4ce45dd37e68dec3c3e1f962e8d347..1fda60c021eed7f744a53d30e97799cae93d8940 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -202,7 +202,7 @@ fn visit_value(&mut self, mplace: &MPlaceTy<'tcx>) -> InterpResult<'tcx> { if let ty::Dynamic(..) = tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind() { - let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta()); + let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta())?; if let Some(alloc_id) = ptr.provenance { // Explicitly choose const mode here, since vtables are immutable, even // if the reference of the fat pointer is mutable. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a02115a110b7b734d1ba6cf0f4ceb64e22612c56..556a44a52381960ba47bae4242f04ef315767e73 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1102,30 +1102,38 @@ pub fn mem_copy_repeatedly( /// Machine pointer introspection. impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - pub fn scalar_to_ptr(&self, scalar: Scalar) -> Pointer> { + pub fn scalar_to_ptr( + &self, + scalar: Scalar, + ) -> InterpResult<'tcx, Pointer>> { // We use `to_bits_or_ptr_internal` since we are just implementing the method people need to // call to force getting out a pointer. - match scalar.to_bits_or_ptr_internal(self.pointer_size()) { - Err(ptr) => ptr.into(), - Ok(bits) => { - let addr = u64::try_from(bits).unwrap(); - let ptr = M::ptr_from_addr(&self, addr); - if addr == 0 { - assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId"); + Ok( + match scalar + .to_bits_or_ptr_internal(self.pointer_size()) + .map_err(|s| err_ub!(ScalarSizeMismatch(s)))? + { + Err(ptr) => ptr.into(), + Ok(bits) => { + let addr = u64::try_from(bits).unwrap(); + let ptr = M::ptr_from_addr(&self, addr); + if addr == 0 { + assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId"); + } + ptr } - ptr - } - } + }, + ) } /// Test if this value might be null. /// If the machine does not support ptr-to-int casts, this is conservative. - pub fn scalar_may_be_null(&self, scalar: Scalar) -> bool { - match scalar.try_to_int() { + pub fn scalar_may_be_null(&self, scalar: Scalar) -> InterpResult<'tcx, bool> { + Ok(match scalar.try_to_int() { Ok(int) => int.is_null(), Err(_) => { // Can only happen during CTFE. - let ptr = self.scalar_to_ptr(scalar); + let ptr = self.scalar_to_ptr(scalar)?; match self.ptr_try_get_alloc_id(ptr) { Ok((alloc_id, offset, _)) => { let (size, _align) = self @@ -1138,7 +1146,7 @@ pub fn scalar_may_be_null(&self, scalar: Scalar) -> bool { Err(_offset) => bug!("a non-int scalar is always a pointer"), } } - } + }) } /// Turning a "maybe pointer" into a proper pointer (and some information diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index ee1ba60829316834b34bbaf3996ebbf686f9edcb..dfc0028e87fcc92a2ebd04f8a71dbd06a7e4a229 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -342,7 +342,7 @@ pub fn read_pointer( &self, op: &OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Pointer>> { - Ok(self.scalar_to_ptr(self.read_scalar(op)?.check_init()?)) + self.scalar_to_ptr(self.read_scalar(op)?.check_init()?) } // Turn the wide MPlace into a string (must already be dereferenced!) @@ -738,7 +738,7 @@ pub fn read_discriminant( // okay. Everything else, we conservatively reject. let ptr_valid = niche_start == 0 && variants_start == variants_end - && !self.scalar_may_be_null(tag_val); + && !self.scalar_may_be_null(tag_val)?; if !ptr_valid { throw_ub!(InvalidTag(dbg_val)) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 5f7f52ef9e9f4e170002f9d951583f93d30cf742..51d47af2f8e24c960db26a3619dd4fd82bda3588 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -281,7 +281,7 @@ pub fn ref_to_mplace( }; let mplace = MemPlace { - ptr: self.scalar_to_ptr(ptr.check_init()?), + ptr: self.scalar_to_ptr(ptr.check_init()?)?, // We could use the run-time alignment here. For now, we do not, because // the point of tracking the alignment here is to make sure that the *static* // alignment information emitted with the loads is correct. The run-time @@ -1104,7 +1104,7 @@ pub(super) fn unpack_dyn_trait( &self, mplace: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> { - let vtable = self.scalar_to_ptr(mplace.vtable()); // also sanity checks the type + let vtable = self.scalar_to_ptr(mplace.vtable())?; // also sanity checks the type let (instance, ty) = self.read_drop_type_from_vtable(vtable)?; let layout = self.layout_of(ty)?; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index c2a38c6978bfb117750c7fc983240f99e380b45c..c2664565f15cb18b7dce2a22621f7537769e2678 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -519,7 +519,7 @@ pub(crate) fn eval_fn_call( .kind(), ty::Dynamic(..) )); - let vtable = self.scalar_to_ptr(receiver_place.meta.unwrap_meta()); + let vtable = self.scalar_to_ptr(receiver_place.meta.unwrap_meta())?; let fn_val = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; // `*mut receiver_place.layout.ty` is almost the layout that we diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 5cf3807faaa6d10922e721cfe5c8509ca4be7792..235938422a89313e99ebc0254a2457addfb75752 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -50,7 +50,7 @@ pub fn get_vtable_slot( let vtable_slot = self .get_ptr_alloc(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); - let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?); + let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?)?; self.get_ptr_fn(fn_ptr) } @@ -75,7 +75,7 @@ pub fn read_drop_type_from_vtable( .check_init()?; // We *need* an instance here, no other kind of function value, to be able // to determine the type. - let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; + let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn)?)?.as_instance()?; trace!("Found drop fn: {:?}", drop_instance); let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig); @@ -132,7 +132,8 @@ pub fn read_new_vtable_after_trait_upcasting_from_vtable( .get_ptr_alloc(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); - let new_vtable = self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?); + let new_vtable = + self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?)?; Ok(new_vtable) } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 349806d997945f1bc3458c065cb4f23a81cc286b..4a0aa41de739b3caa13f0ed80fa3170fc8c3d331 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -312,7 +312,7 @@ fn check_wide_ptr_meta( let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); match tail.kind() { ty::Dynamic(..) => { - let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta()); + let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta())?; // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( self.ecx.check_ptr_access_align( @@ -577,7 +577,7 @@ fn try_visit_primitive( // If we check references recursively, also check that this points to a function. if let Some(_) = self.ref_tracking { - let ptr = self.ecx.scalar_to_ptr(value); + let ptr = self.ecx.scalar_to_ptr(value)?; let _fn = try_validation!( self.ecx.get_ptr_fn(ptr), self.path, @@ -590,7 +590,7 @@ fn try_visit_primitive( // FIXME: Check if the signature matches } else { // Otherwise (for standalone Miri), we have to still check it to be non-null. - if self.ecx.scalar_may_be_null(value) { + if self.ecx.scalar_may_be_null(value)? { throw_validation_failure!(self.path, { "a null function pointer" }); } } @@ -667,7 +667,7 @@ fn visit_scalar( // We support 2 kinds of ranges here: full range, and excluding zero. if start == 1 && end == max_value { // Only null is the niche. So make sure the ptr is NOT null. - if self.ecx.scalar_may_be_null(value) { + if self.ecx.scalar_may_be_null(value)? { throw_validation_failure!(self.path, { "a potentially null pointer" } expected { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 63f2bc51aeeaa2a45f5df3cce07265ddab7b91d5..438f356f072c6d863e093668d022327785efb3d9 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -15,8 +15,8 @@ use super::{ read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, Provenance, - ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, UndefinedBehaviorInfo, UninitBytesAccess, - UnsupportedOpInfo, + ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, ScalarSizeMismatch, UndefinedBehaviorInfo, + UninitBytesAccess, UnsupportedOpInfo, }; use crate::ty; @@ -81,6 +81,8 @@ pub fn inner(self) -> &'tcx Allocation { /// is added when converting to `InterpError`. #[derive(Debug)] pub enum AllocError { + /// A scalar had the wrong size. + ScalarSizeMismatch(ScalarSizeMismatch), /// Encountered a pointer where we needed raw bytes. ReadPointerAsBytes, /// Partially overwriting a pointer. @@ -90,10 +92,19 @@ pub enum AllocError { } pub type AllocResult = Result; +impl From for AllocError { + fn from(s: ScalarSizeMismatch) -> Self { + AllocError::ScalarSizeMismatch(s) + } +} + impl AllocError { pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpError<'tcx> { use AllocError::*; match self { + ScalarSizeMismatch(s) => { + InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s)) + } ReadPointerAsBytes => InterpError::Unsupported(UnsupportedOpInfo::ReadPointerAsBytes), PartialPointerOverwrite(offset) => InterpError::Unsupported( UnsupportedOpInfo::PartialPointerOverwrite(Pointer::new(alloc_id, offset)), @@ -425,7 +436,7 @@ pub fn write_scalar( // `to_bits_or_ptr_internal` is the right method because we just want to store this data // as-is into memory. - let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size) { + let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? { Err(val) => { let (provenance, offset) = val.into_parts(); (u128::from(offset.bytes()), Some(provenance)) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 492091a4f25405f5ed1a47161e8fda432e5752cf..9afe9523fcab0438f102cf84226e57f6ee5df2b5 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -221,6 +221,13 @@ pub struct UninitBytesAccess { pub uninit_size: Size, } +/// Information about a size mismatch. +#[derive(Debug)] +pub struct ScalarSizeMismatch { + pub target_size: u64, + pub data_size: u64, +} + /// Error information for when the program caused Undefined Behavior. pub enum UndefinedBehaviorInfo<'tcx> { /// Free-form case. Only for errors that are never caught! @@ -298,10 +305,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Working with a local that is not currently live. DeadLocal, /// Data size is not equal to target size. - ScalarSizeMismatch { - target_size: u64, - data_size: u64, - }, + ScalarSizeMismatch(ScalarSizeMismatch), /// A discriminant of an uninhabited enum variant is written. UninhabitedEnumVariantWritten, } @@ -408,7 +412,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "using uninitialized data, but this operation requires initialized memory" ), DeadLocal => write!(f, "accessing a dead local variable"), - ScalarSizeMismatch { target_size, data_size } => write!( + ScalarSizeMismatch(self::ScalarSizeMismatch { target_size, data_size }) => write!( f, "scalar size mismatch: expected {} bytes but got {} bytes instead", target_size, data_size diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index bce962491b7b1c99c17b43139d2743c12d78ebe6..d8cba39c6d97bf9bc58a14321f8f12646e86d081 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -120,7 +120,8 @@ pub use self::error::{ struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, - ResourceExhaustionInfo, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo, + ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, + UnsupportedOpInfo, }; pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit}; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 8e32603a357026f9b4af0b6fa1d8eccea5f83df8..9cffdf2993ed5bdb97c2ddba9a2beddb0a3ae61c 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -12,6 +12,7 @@ use super::{ AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance, + ScalarSizeMismatch, }; /// Represents the result of const evaluation via the `eval_to_allocation` query. @@ -300,16 +301,29 @@ pub fn from_f64(f: Double) -> Self { /// /// This method only exists for the benefit of low-level operations that truly need to treat the /// scalar in whatever form it is. + /// + /// 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) -> Result> { + pub fn to_bits_or_ptr_internal( + self, + target_size: Size, + ) -> Result>, ScalarSizeMismatch> { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); - match self { - Scalar::Int(int) => Ok(int.assert_bits(target_size)), + Ok(match self { + Scalar::Int(int) => Ok(int.to_bits(target_size).map_err(|size| { + ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes() } + })?), Scalar::Ptr(ptr, sz) => { - assert_eq!(target_size.bytes(), u64::from(sz)); + if target_size.bytes() != sz.into() { + return Err(ScalarSizeMismatch { + target_size: target_size.bytes(), + data_size: sz.into(), + }); + } Err(ptr) } - } + }) } } @@ -348,10 +362,10 @@ pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err( |size| { - err_ub!(ScalarSizeMismatch { + err_ub!(ScalarSizeMismatch(ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes(), - }) + })) .into() }, ) 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 1fadd0c26fc49d2306fdd88eaa3023bd5d79c41e..bb3ba3e596d1449b996ec065eaab5108b26344ce 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -146,7 +146,7 @@ fn from_const<'tcx>( // straight to the result, after doing a bit of checking. (We // could remove this branch and just fall through, which // is more general but much slower.) - if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size) { + if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size).unwrap() { return Some(bits); } }