about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2021-07-16 09:39:35 +0200
committerRalf Jung <post@ralfj.de>2021-07-16 10:09:56 +0200
commit7c720ce6121dd878b25f8e6a645a07563e5a4b01 (patch)
tree1aa40698e47dde0b95b0d78522fb8839f8e0c54c
parent4e280656189588a3cc30b86599a0ff4f211030b8 (diff)
downloadrust-7c720ce6121dd878b25f8e6a645a07563e5a4b01.tar.gz
rust-7c720ce6121dd878b25f8e6a645a07563e5a4b01.zip
get rid of incorrect erase_for_fmt
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs26
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs52
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs10
-rw-r--r--compiler/rustc_mir/src/interpret/eval_context.rs14
-rw-r--r--compiler/rustc_mir/src/interpret/intrinsics.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/memory.rs14
-rw-r--r--compiler/rustc_mir/src/interpret/operand.rs36
-rw-r--r--compiler/rustc_mir/src/interpret/place.rs23
-rw-r--r--compiler/rustc_mir/src/interpret/validity.rs13
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs2
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);
                     }
                 }