diff options
| author | Ralf Jung <post@ralfj.de> | 2021-07-16 09:39:35 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2021-07-16 10:09:56 +0200 |
| commit | 7c720ce6121dd878b25f8e6a645a07563e5a4b01 (patch) | |
| tree | 1aa40698e47dde0b95b0d78522fb8839f8e0c54c | |
| parent | 4e280656189588a3cc30b86599a0ff4f211030b8 (diff) | |
| download | rust-7c720ce6121dd878b25f8e6a645a07563e5a4b01.tar.gz rust-7c720ce6121dd878b25f8e6a645a07563e5a4b01.zip | |
get rid of incorrect erase_for_fmt
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/allocation.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/pointer.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/value.rs | 52 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/print/pretty.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/eval_context.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/intrinsics.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/memory.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/operand.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/place.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/validity.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/transform/const_prop.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs | 2 |
12 files changed, 81 insertions, 119 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 6b2d0fc1a0e..56b8f9b928f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -377,7 +377,9 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> { } }; - let (bytes, provenance) = match val.to_bits_or_ptr(range.size) { + // `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) { Err(val) => { let (provenance, offset) = val.into_parts(); (u128::from(offset.bytes()), Some(provenance)) diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 307d7d28462..c7daaec8d5d 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -89,7 +89,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {} pub trait Provenance: Copy { /// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address. /// If `true, ptr-to-int casts work by simply discarding the provenance. - /// If `false`, ptr-to-int casts are not supported. + /// If `false`, ptr-to-int casts are not supported. The offset *must* be relative in that case. const OFFSET_IS_ADDR: bool; /// Determines how a pointer should be printed. @@ -97,8 +97,9 @@ pub trait Provenance: Copy { where Self: Sized; - /// "Erasing" a tag converts it to the default tag type if possible. Used only for formatting purposes! - fn erase_for_fmt(self) -> AllocId; + /// Provenance must always be able to identify the allocation this ptr points to. + /// (Identifying the offset in that allocation, however, is harder -- use `Memory::ptr_get_alloc` for that.) + fn get_alloc_id(self) -> AllocId; } impl Provenance for AllocId { @@ -120,7 +121,7 @@ impl Provenance for AllocId { Ok(()) } - fn erase_for_fmt(self) -> AllocId { + fn get_alloc_id(self) -> AllocId { self } } @@ -177,14 +178,6 @@ impl<Tag> Pointer<Option<Tag>> { None => Err(self.offset), } } - - #[inline(always)] - pub fn map_erase_for_fmt(self) -> Pointer<Option<AllocId>> - where - Tag: Provenance, - { - Pointer { offset: self.offset, provenance: self.provenance.map(Provenance::erase_for_fmt) } - } } impl<Tag> Pointer<Option<Tag>> { @@ -208,15 +201,6 @@ impl<'tcx, Tag> Pointer<Tag> { (self.provenance, self.offset) } - #[inline(always)] - pub fn erase_for_fmt(self) -> Pointer - where - Tag: Provenance, - { - // FIXME: This is wrong! `self.offset` might be an absolute address. - Pointer { offset: self.offset, provenance: self.provenance.erase_for_fmt() } - } - pub fn map_provenance(self, f: impl FnOnce(Tag) -> Tag) -> Self { Pointer { provenance: f(self.provenance), ..self } } diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 1be04f8c18b..62b71b10d5a 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -289,9 +289,10 @@ impl<Tag> Scalar<Tag> { /// This is almost certainly not the method you want! You should dispatch on the type /// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed. /// - /// This method only exists for the benefit of low-level memory operations. + /// This method only exists for the benefit of low-level operations that truly need to treat the + /// scalar in whatever form it is. #[inline] - pub fn to_bits_or_ptr(self, target_size: Size) -> Result<u128, Pointer<Tag>> { + pub fn to_bits_or_ptr_internal(self, target_size: Size) -> Result<u128, Pointer<Tag>> { 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)), @@ -304,32 +305,23 @@ impl<Tag> Scalar<Tag> { } impl<'tcx, Tag: Provenance> Scalar<Tag> { - /// Erase the tag from the scalar, if any. - /// - /// Used by error reporting code to avoid having the error type depend on `Tag`. - #[inline] - pub fn erase_for_fmt(self) -> Scalar { - match self { - Scalar::Ptr(ptr, sz) => Scalar::Ptr(ptr.erase_for_fmt(), sz), - Scalar::Int(int) => Scalar::Int(int), - } - } - /// Fundamental scalar-to-int (cast) operation. Many convenience wrappers exist below, that you /// likely want to use instead. /// /// Will perform ptr-to-int casts if needed and possible. + /// If that fails, we know the offset is relative, so we return an "erased" Scalar + /// (which is useful for error messages but not much else). #[inline] - pub fn try_to_int(self) -> Option<ScalarInt> { + pub fn try_to_int(self) -> Result<ScalarInt, Scalar<AllocId>> { match self { - Scalar::Int(int) => Some(int), + Scalar::Int(int) => Ok(int), Scalar::Ptr(ptr, sz) => { if Tag::OFFSET_IS_ADDR { - Some( - ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap(), - ) + Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap()) } else { - None + // We know `offset` is relative, since `OFFSET_IS_ADDR == false`. + let (tag, offset) = ptr.into_parts(); + Err(Scalar::Ptr(Pointer::new(tag.get_alloc_id(), offset), sz)) } } } @@ -340,19 +332,20 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> { self.try_to_int().unwrap() } + /// 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(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() - .ok_or_else(|| err_unsup!(ReadPointerAsBytes))? - .to_bits(target_size) - .map_err(|size| { + self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err( + |size| { err_ub!(ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes(), }) .into() - }) + }, + ) } #[inline(always)] @@ -522,17 +515,6 @@ impl<Tag> ScalarMaybeUninit<Tag> { } impl<'tcx, Tag: Provenance> ScalarMaybeUninit<Tag> { - /// Erase the tag from the scalar, if any. - /// - /// Used by error reporting code to avoid having the error type depend on `Tag`. - #[inline] - pub fn erase_for_fmt(self) -> ScalarMaybeUninit { - match self { - ScalarMaybeUninit::Scalar(s) => ScalarMaybeUninit::Scalar(s.erase_for_fmt()), - ScalarMaybeUninit::Uninit => ScalarMaybeUninit::Uninit, - } - } - #[inline(always)] pub fn to_bool(self) -> InterpResult<'tcx, bool> { self.check_init()?.to_bool() diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index dbdca44952f..6dfbd28f776 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,5 +1,5 @@ use crate::middle::cstore::{ExternCrate, ExternCrateSource}; -use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Scalar}; +use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; @@ -1107,9 +1107,9 @@ pub trait PrettyPrinter<'tcx>: /// This is overridden for MIR printing because we only want to hide alloc ids from users, not /// from MIR where it is actually useful. - fn pretty_print_const_pointer( + fn pretty_print_const_pointer<Tag: Provenance>( mut self, - _: Pointer, + _: Pointer<Tag>, ty: Ty<'tcx>, print_ty: bool, ) -> Result<Self::Const, Self::Error> { @@ -1680,9 +1680,9 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { } } - fn pretty_print_const_pointer( + fn pretty_print_const_pointer<Tag: Provenance>( self, - p: Pointer, + p: Pointer<Tag>, ty: Ty<'tcx>, print_ty: bool, ) -> Result<Self::Const, Self::Error> { diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 71e4652ac00..b130eb3ca0c 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -897,11 +897,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn deallocate_local(&mut self, local: LocalValue<M::PointerTag>) -> InterpResult<'tcx> { if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local { // All locals have a backing allocation, even if the allocation is empty - // due to the local having ZST type. + // due to the local having ZST type. Hence we can `unwrap`. trace!( "deallocating local {:?}: {:?}", local, - self.memory.dump_alloc(ptr.provenance.unwrap().erase_for_fmt()) + self.memory.dump_alloc(ptr.provenance.unwrap().get_alloc_id()) ); self.memory.deallocate(ptr, None, MemoryKind::Stack)?; }; @@ -989,28 +989,28 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug }, mplace.ptr, )?; - allocs.extend(mplace.ptr.map_erase_for_fmt().provenance); + allocs.extend(mplace.ptr.provenance.map(Provenance::get_alloc_id)); } LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => { write!(fmt, " {:?}", val)?; if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val { - allocs.push(ptr.provenance.erase_for_fmt()); + allocs.push(ptr.provenance.get_alloc_id()); } } LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => { write!(fmt, " ({:?}, {:?})", val1, val2)?; if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val1 { - allocs.push(ptr.provenance.erase_for_fmt()); + allocs.push(ptr.provenance.get_alloc_id()); } if let ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _size)) = val2 { - allocs.push(ptr.provenance.erase_for_fmt()); + allocs.push(ptr.provenance.get_alloc_id()); } } } write!(fmt, ": {:?}", self.ecx.memory.dump_allocs(allocs)) } - Place::Ptr(mplace) => match mplace.ptr.map_erase_for_fmt().provenance { + Place::Ptr(mplace) => match mplace.ptr.provenance.map(Provenance::get_alloc_id) { Some(alloc_id) => write!( fmt, "by align({}) ref {:?}: {:?}", diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index 9335b783c77..dc1f9053b61 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -362,7 +362,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // // Control flow is weird because we cannot early-return (to reach the // `go_to_block` at the end). - let done = if let (Some(a), Some(b)) = (a.try_to_int(), b.try_to_int()) { + let done = if let (Ok(a), Ok(b)) = (a.try_to_int(), b.try_to_int()) { let a = a.try_to_machine_usize(*self.tcx).unwrap(); let b = b.try_to_machine_usize(*self.tcx).unwrap(); if a == b && a != 0 { diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 564b3429c05..b82dbf3e94b 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -757,12 +757,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ptr: Pointer<Option<M::PointerTag>>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { trace!("get_fn({:?})", ptr); - let (alloc_id, offset, ptr) = self.ptr_get_alloc(ptr)?; + let (alloc_id, offset, _ptr) = self.ptr_get_alloc(ptr)?; if offset.bytes() != 0 { - throw_ub!(InvalidFunctionPointer(ptr.erase_for_fmt())) + throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))) } self.get_fn_alloc(alloc_id) - .ok_or_else(|| err_ub!(InvalidFunctionPointer(ptr.erase_for_fmt())).into()) + .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))).into()) } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { @@ -801,7 +801,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if reachable.insert(id) { // This is a new allocation, add its relocations to `todo`. if let Some((_, alloc)) = self.alloc_map.get(id) { - todo.extend(alloc.relocations().values().map(|tag| tag.erase_for_fmt())); + todo.extend(alloc.relocations().values().map(|tag| tag.get_alloc_id())); } } } @@ -841,7 +841,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, allocs_to_print: &mut VecDeque<AllocId>, alloc: &Allocation<Tag, Extra>, ) -> std::fmt::Result { - for alloc_id in alloc.relocations().values().map(|tag| tag.erase_for_fmt()) { + for alloc_id in alloc.relocations().values().map(|tag| tag.get_alloc_id()) { allocs_to_print.push_back(alloc_id); } write!(fmt, "{}", pretty::display_allocation(tcx, alloc)) @@ -1129,7 +1129,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// Machine pointer introspection. impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn scalar_to_ptr(&self, scalar: Scalar<M::PointerTag>) -> Pointer<Option<M::PointerTag>> { - match scalar.to_bits_or_ptr(self.pointer_size()) { + // 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(); diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index fefda32bfe6..04d4e3993e4 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -118,8 +118,14 @@ impl<Tag: Provenance> std::fmt::Display for ImmTy<'tcx, Tag> { ty: Ty<'tcx>, ) -> Result<FmtPrinter<'a, 'tcx, F>, std::fmt::Error> { match s { - ScalarMaybeUninit::Scalar(s) => { - cx.pretty_print_const_scalar(s.erase_for_fmt(), ty, true) + ScalarMaybeUninit::Scalar(Scalar::Int(int)) => { + cx.pretty_print_const_scalar_int(int, ty, true) + } + ScalarMaybeUninit::Scalar(Scalar::Ptr(ptr, _sz)) => { + // Just print the ptr value. `pretty_print_const_scalar_ptr` would also try to + // print what is points to, which would fail since it has no access to the local + // memory. + cx.pretty_print_const_pointer(ptr, ty, true) } ScalarMaybeUninit::Uninit => cx.typed_value( |mut this| { @@ -139,11 +145,11 @@ impl<Tag: Provenance> std::fmt::Display for ImmTy<'tcx, Tag> { p(cx, s, ty)?; return Ok(()); } - write!(f, "{}: {}", s.erase_for_fmt(), self.layout.ty) + write!(f, "{}: {}", s, self.layout.ty) } Immediate::ScalarPair(a, b) => { // FIXME(oli-obk): at least print tuples and slices nicely - write!(f, "({}, {}): {}", a.erase_for_fmt(), b.erase_for_fmt(), self.layout.ty,) + write!(f, "({}, {}): {}", a, b, self.layout.ty,) } } }) @@ -693,8 +699,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(match *tag_encoding { TagEncoding::Direct => { let tag_bits = tag_val - .to_bits(tag_layout.size) - .map_err(|_| err_ub!(InvalidTag(tag_val.erase_for_fmt())))?; + .try_to_int() + .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))? + .assert_bits(tag_layout.size); // Cast bits from tag layout to discriminant layout. let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty); let discr_bits = discr_val.assert_bits(discr_layout.size); @@ -711,7 +718,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"), } - .ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_for_fmt())))?; + .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?; // Return the cast value, and the index. (discr_val, index.0) } @@ -720,18 +727,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // discriminant (encoded in niche/tag) and variant index are the same. let variants_start = niche_variants.start().as_u32(); let variants_end = niche_variants.end().as_u32(); - let variant = match tag_val.to_bits_or_ptr(tag_layout.size) { - Err(ptr) => { - // The niche must be just 0 (which an inbounds pointer value never is) + let variant = match tag_val.try_to_int() { + Err(dbg_val) => { + // So this is a pointer then, and casting to an int failed. + // Can only happen during CTFE. + let ptr = self.scalar_to_ptr(tag_val); + // The niche must be just 0, and the ptr not null, then we know this is + // okay. Everything else, we conservatively reject. let ptr_valid = niche_start == 0 && variants_start == variants_end - && !self.memory.ptr_may_be_null(ptr.into()); + && !self.memory.ptr_may_be_null(ptr); if !ptr_valid { - throw_ub!(InvalidTag(tag_val.erase_for_fmt())) + throw_ub!(InvalidTag(dbg_val)) } dataful_variant } Ok(tag_bits) => { + let tag_bits = tag_bits.assert_bits(tag_layout.size); // We need to use machine arithmetic to get the relative variant idx: // variant_index_relative = tag_val - niche_start_val let tag_val = ImmTy::from_uint(tag_bits, tag_layout); diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs index 5b0a940637d..419c17595a1 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_mir/src/interpret/place.rs @@ -62,17 +62,6 @@ impl<Tag> MemPlaceMeta<Tag> { Self::None | Self::Poison => false, } } - - pub fn erase_for_fmt(self) -> MemPlaceMeta - where - Tag: Provenance, - { - match self { - Self::Meta(s) => MemPlaceMeta::Meta(s.erase_for_fmt()), - Self::None => MemPlaceMeta::None, - Self::Poison => MemPlaceMeta::Poison, - } - } } #[derive(Copy, Clone, Hash, PartialEq, Eq, HashStable)] @@ -182,18 +171,6 @@ impl<'tcx, Tag> From<MPlaceTy<'tcx, Tag>> for PlaceTy<'tcx, Tag> { } impl<Tag> MemPlace<Tag> { - #[inline] - pub fn erase_for_fmt(self) -> MemPlace - where - Tag: Provenance, - { - MemPlace { - ptr: self.ptr.map_erase_for_fmt(), - align: self.align, - meta: self.meta.erase_for_fmt(), - } - } - #[inline(always)] pub fn from_ptr(ptr: Pointer<Option<Tag>>, align: Align) -> Self { MemPlace { ptr, align, meta: MemPlaceMeta::None } diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs index 2d4eb0b8238..0c7f89c1a36 100644 --- a/compiler/rustc_mir/src/interpret/validity.rs +++ b/compiler/rustc_mir/src/interpret/validity.rs @@ -535,7 +535,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // types below! if self.ctfe_mode.is_some() { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous - let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_some()); + let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok()); if !is_bits { throw_validation_failure!(self.path, { "{}", value } expected { "initialized plain (non-pointer) bytes" } @@ -652,11 +652,14 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' err_ub!(InvalidUninitBytes(None)) => { "{}", value } expected { "something {}", wrapping_range_format(valid_range, max_hi) }, ); - let bits = match value.to_bits_or_ptr(op.layout.size) { - Err(ptr) => { + let bits = match value.try_to_int() { + Err(_) => { + // So this is a pointer then, and casting to an int failed. + // Can only happen during CTFE. + let ptr = self.ecx.scalar_to_ptr(value); if lo == 1 && hi == max_hi { // Only null is the niche. So make sure the ptr is NOT null. - if self.ecx.memory.ptr_may_be_null(ptr.into()) { + if self.ecx.memory.ptr_may_be_null(ptr) { throw_validation_failure!(self.path, { "a potentially null pointer" } expected { @@ -678,7 +681,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' ) } } - Ok(data) => data, + Ok(int) => int.assert_bits(op.layout.size), }; // Now compare. This is slightly subtle because this is a special "wrap-around" range. if wrapping_range_contains(&valid_range, bits) { diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 5e2c47be3a2..e02e41d6206 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -921,12 +921,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { match **op { interpret::Operand::Immediate(Immediate::Scalar(ScalarMaybeUninit::Scalar(s))) => { - s.try_to_int().is_some() + s.try_to_int().is_ok() } interpret::Operand::Immediate(Immediate::ScalarPair( ScalarMaybeUninit::Scalar(l), ScalarMaybeUninit::Scalar(r), - )) => l.try_to_int().is_some() && r.try_to_int().is_some(), + )) => l.try_to_int().is_ok() && r.try_to_int().is_ok(), _ => false, } } 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 db15f6dad3c..ace13ea4462 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -123,7 +123,7 @@ impl IntRange { // 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(target_size) { + if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size) { return Some(bits); } } |
