summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-07-19 20:04:08 +0200
committerRalf Jung <post@ralfj.de>2025-07-20 22:14:27 +0200
commit3f9be406a6fd879a99a0eba33cc196fa2cb3957b (patch)
tree640b295bc5b57132a450008fbb6cc38c7c72fb58 /compiler
parent9982d6462bedf1e793f7b2dbd655a4e57cdf67d4 (diff)
downloadrust-3f9be406a6fd879a99a0eba33cc196fa2cb3957b.tar.gz
rust-3f9be406a6fd879a99a0eba33cc196fa2cb3957b.zip
fix handling of base address for TypeId allocations
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs16
2 files changed, 18 insertions, 16 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index f24fb18f83b..a18ae79f318 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -279,23 +279,15 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
     fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
         interp_ok(match (a, b) {
             // Comparisons between integers are always known.
-            (Scalar::Int { .. }, Scalar::Int { .. }) => {
-                if a == b {
-                    1
-                } else {
-                    0
-                }
-            }
-            // Comparisons of abstract pointers with null pointers are known if the pointer
-            // is in bounds, because if they are in bounds, the pointer can't be null.
-            // Inequality with integers other than null can never be known for sure.
-            (Scalar::Int(int), ptr @ Scalar::Ptr(..))
-            | (ptr @ Scalar::Ptr(..), Scalar::Int(int))
+            (Scalar::Int(a), Scalar::Int(b)) => (a == b) as u8,
+            // Comparisons of null with an arbitrary scalar can be known if `scalar_may_be_null`
+            // indicates that the scalar can definitely *not* be null.
+            (Scalar::Int(int), ptr) | (ptr, Scalar::Int(int))
                 if int.is_null() && !self.scalar_may_be_null(ptr)? =>
             {
                 0
             }
-            // Equality with integers can never be known for sure.
+            // Other ways of comparing integers and pointers can never be known for sure.
             (Scalar::Int { .. }, Scalar::Ptr(..)) | (Scalar::Ptr(..), Scalar::Int { .. }) => 2,
             // FIXME: return a `1` for when both sides are the same pointer, *except* that
             // some things (like functions and vtables) do not have stable addresses
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 20c8e983cea..34297a61648 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -67,8 +67,10 @@ pub enum AllocKind {
     LiveData,
     /// A function allocation (that fn ptrs point to).
     Function,
-    /// A "virtual" allocation, used for vtables and TypeId.
-    Virtual,
+    /// A vtable allocation.
+    VTable,
+    /// A TypeId allocation.
+    TypeId,
     /// A dead allocation.
     Dead,
 }
@@ -952,7 +954,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             let kind = match global_alloc {
                 GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
                 GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),
-                GlobalAlloc::VTable { .. } | GlobalAlloc::TypeId { .. } => AllocKind::Virtual,
+                GlobalAlloc::VTable { .. } => AllocKind::VTable,
+                GlobalAlloc::TypeId { .. } => AllocKind::TypeId,
             };
             return AllocInfo::new(size, align, kind, mutbl);
         }
@@ -1617,6 +1620,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 match self.ptr_try_get_alloc_id(ptr, 0) {
                     Ok((alloc_id, offset, _)) => {
                         let info = self.get_alloc_info(alloc_id);
+                        if matches!(info.kind, AllocKind::TypeId) {
+                            // We *could* actually precisely answer this question since here,
+                            // the offset *is* the integer value. But the entire point of making
+                            // this a pointer is not to leak the integer value, so we say everything
+                            // might be null.
+                            return interp_ok(true);
+                        }
                         // If the pointer is in-bounds (including "at the end"), it is definitely not null.
                         if offset <= info.size {
                             return interp_ok(false);