about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs8
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs49
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs7
-rw-r--r--library/core/src/intrinsics.rs25
-rw-r--r--library/core/src/ptr/const_ptr.rs55
-rw-r--r--library/core/src/ptr/mut_ptr.rs49
-rw-r--r--src/test/ui/consts/miri_unleashed/slice_eq.rs12
-rw-r--r--src/test/ui/consts/ptr_comparisons.rs24
-rw-r--r--src/test/ui/consts/ptr_comparisons.stderr14
12 files changed, 119 insertions, 138 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 0cd9332a58b..2e4ca594f91 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -816,20 +816,13 @@ fn codegen_regular_intrinsic_call<'tcx>(
             ret.write_cvalue(fx, val);
         }
 
-        sym::ptr_guaranteed_eq => {
+        sym::ptr_guaranteed_cmp => {
             intrinsic_args!(fx, args => (a, b); intrinsic);
 
             let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b);
             ret.write_cvalue(fx, val);
         }
 
-        sym::ptr_guaranteed_ne => {
-            intrinsic_args!(fx, args => (a, b); intrinsic);
-
-            let val = crate::num::codegen_ptr_binop(fx, BinOp::Ne, a, b);
-            ret.write_cvalue(fx, val);
-        }
-
         sym::caller_location => {
             intrinsic_args!(fx, args => (); intrinsic);
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 6393dd9d634..215edbe02c0 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -551,14 +551,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 return;
             }
 
-            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
+            sym::ptr_guaranteed_cmp => {
                 let a = args[0].immediate();
                 let b = args[1].immediate();
-                if name == sym::ptr_guaranteed_eq {
-                    bx.icmp(IntPredicate::IntEQ, a, b)
-                } else {
-                    bx.icmp(IntPredicate::IntNE, a, b)
-                }
+                bx.icmp(IntPredicate::IntEQ, a, b)
             }
 
             sym::ptr_offset_from | sym::ptr_offset_from_unsigned => {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 6e5c840bdfd..e5acacd9188 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -191,34 +191,35 @@ impl interpret::MayLeak for ! {
 }
 
 impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
-    fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, bool> {
+    /// See documentation on the `ptr_guaranteed_cmp` intrinsic.
+    fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
         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.
-            (Scalar::Int { .. }, Scalar::Ptr(..)) | (Scalar::Ptr(..), Scalar::Int { .. }) => false,
-            // FIXME: return `true` for when both sides are the same pointer, *except* that
-            // 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) -> InterpResult<'tcx, bool> {
-        Ok(match (a, b) {
-            // Comparisons between integers are always known.
-            (Scalar::Int(_), Scalar::Int(_)) => a != b,
+            (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)) => {
-                int.is_null() && !self.scalar_may_be_null(ptr)?
+            | (ptr @ Scalar::Ptr(..), Scalar::Int(int))
+                if int.is_null() && !self.scalar_may_be_null(ptr)? =>
+            {
+                0
             }
-            // FIXME: return `true` for at least some comparisons where we can reliably
+            // Equality with integers 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
+            // so we need to be careful around them (see e.g. #73722).
+            // FIXME: return `0` 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,
+            (Scalar::Ptr(..), Scalar::Ptr(..)) => 2,
         })
     }
 }
@@ -329,15 +330,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
             throw_unsup_format!("intrinsic `{intrinsic_name}` is not supported at compile-time");
         };
         match intrinsic_name {
-            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
+            sym::ptr_guaranteed_cmp => {
                 let a = ecx.read_scalar(&args[0])?;
                 let b = ecx.read_scalar(&args[1])?;
-                let cmp = if intrinsic_name == sym::ptr_guaranteed_eq {
-                    ecx.guaranteed_eq(a, b)?
-                } else {
-                    ecx.guaranteed_ne(a, b)?
-                };
-                ecx.write_scalar(Scalar::from_bool(cmp), dest)?;
+                let cmp = ecx.guaranteed_cmp(a, b)?;
+                ecx.write_scalar(Scalar::from_u8(cmp), dest)?;
             }
             sym::const_allocate => {
                 let size = ecx.read_scalar(&args[0])?.to_machine_usize(ecx)?;
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 8b7c3cf3377..a964fe8465e 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -97,7 +97,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
         }
 
         // Raw pointers are not allowed in type level constants, as we cannot properly test them for
-        // equality at compile-time (see `ptr_guaranteed_eq`/`_ne`).
+        // equality at compile-time (see `ptr_guaranteed_cmp`).
         // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
         // agree with runtime equality tests.
         ty::FnPtr(_) | ty::RawPtr(_) => Err(ValTreeCreationError::NonSupportedType),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f2876344c65..9c3d99deae0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1117,8 +1117,7 @@ symbols! {
         profiler_builtins,
         profiler_runtime,
         ptr,
-        ptr_guaranteed_eq,
-        ptr_guaranteed_ne,
+        ptr_guaranteed_cmp,
         ptr_mask,
         ptr_null,
         ptr_null_mut,
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 73dd7122e26..4fa33da50c9 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -95,8 +95,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
         | sym::type_id
         | sym::likely
         | sym::unlikely
-        | sym::ptr_guaranteed_eq
-        | sym::ptr_guaranteed_ne
+        | sym::ptr_guaranteed_cmp
         | sym::minnumf32
         | sym::minnumf64
         | sym::maxnumf32
@@ -302,8 +301,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
             }
 
-            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
-                (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool)
+            sym::ptr_guaranteed_cmp => {
+                (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.u8)
             }
 
             sym::const_allocate => {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 56f5824efd4..11c75e2c912 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2013,21 +2013,24 @@ extern "rust-intrinsic" {
     pub fn ptr_offset_from_unsigned<T>(ptr: *const T, base: *const T) -> usize;
 
     /// See documentation of `<*const T>::guaranteed_eq` for details.
+    /// Returns `2` if the result is unknown.
+    /// Returns `1` if the pointers are guaranteed equal
+    /// Returns `0` if the pointers are guaranteed inequal
     ///
     /// Note that, unlike most intrinsics, this is safe to call;
     /// it does not require an `unsafe` block.
     /// Therefore, implementations must not require the user to uphold
     /// any safety invariants.
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[cfg(not(bootstrap))]
+    pub fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8;
+
+    #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[cfg(bootstrap)]
     pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
 
-    /// See documentation of `<*const T>::guaranteed_ne` for details.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[cfg(bootstrap)]
     pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
 
     /// Allocates a block of memory at compile time.
@@ -2213,6 +2216,16 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
     diff >= size
 }
 
+#[cfg(bootstrap)]
+pub const fn ptr_guaranteed_cmp(a: *const (), b: *const ()) -> u8 {
+    match (ptr_guaranteed_eq(a, b), ptr_guaranteed_ne(a, b)) {
+        (false, false) => 2,
+        (true, false) => 1,
+        (false, true) => 0,
+        (true, true) => unreachable!(),
+    }
+}
+
 /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
 /// and destination must *not* overlap.
 ///
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 80bff74f3e9..fcdf69a7aaa 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -36,7 +36,10 @@ impl<T: ?Sized> *const T {
     pub const fn is_null(self) -> bool {
         // Compare via a cast to a thin pointer, so fat pointers are only
         // considering their "data" part for null-ness.
-        (self as *const u8).guaranteed_eq(null())
+        match (self as *const u8).guaranteed_eq(null()) {
+            None => false,
+            Some(res) => res,
+        }
     }
 
     /// Casts to a pointer of another type.
@@ -770,20 +773,16 @@ impl<T: ?Sized> *const T {
 
     /// Returns whether two pointers are guaranteed to be equal.
     ///
-    /// At runtime this function behaves like `self == other`.
+    /// At runtime this function behaves like `Some(self == other)`.
     /// However, in some contexts (e.g., compile-time evaluation),
     /// it is not always possible to determine equality of two pointers, so this function may
-    /// spuriously return `false` for pointers that later actually turn out to be equal.
-    /// But when it returns `true`, the pointers are guaranteed to be equal.
-    ///
-    /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer
-    /// comparisons for which both functions return `false`.
+    /// spuriously return `None` for pointers that later actually turn out to have its equality known.
+    /// But when it returns `Some`, the pointers' equality is guaranteed to be known.
     ///
-    /// [`guaranteed_ne`]: #method.guaranteed_ne
-    ///
-    /// The return value may change depending on the compiler version and unsafe code must not
+    /// The return value may change from `Some` to `None` and vice versa depending on the compiler
+    /// version and unsafe code must not
     /// rely on the result of this function for soundness. It is suggested to only use this function
-    /// for performance optimizations where spurious `false` return values by this function do not
+    /// for performance optimizations where spurious `None` return values by this function do not
     /// affect the outcome, but just the performance.
     /// The consequences of using this method to make runtime and compile-time code behave
     /// differently have not been explored. This method should not be used to introduce such
@@ -792,29 +791,28 @@ impl<T: ?Sized> *const T {
     #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[inline]
-    pub const fn guaranteed_eq(self, other: *const T) -> bool
+    pub const fn guaranteed_eq(self, other: *const T) -> Option<bool>
     where
         T: Sized,
     {
-        intrinsics::ptr_guaranteed_eq(self, other)
+        match intrinsics::ptr_guaranteed_cmp(self as _, other as _) {
+            2 => None,
+            other => Some(other == 1),
+        }
     }
 
-    /// Returns whether two pointers are guaranteed to be unequal.
+    /// Returns whether two pointers are guaranteed to be inequal.
     ///
-    /// At runtime this function behaves like `self != other`.
+    /// At runtime this function behaves like `Some(self == other)`.
     /// However, in some contexts (e.g., compile-time evaluation),
-    /// it is not always possible to determine the inequality of two pointers, so this function may
-    /// spuriously return `false` for pointers that later actually turn out to be unequal.
-    /// But when it returns `true`, the pointers are guaranteed to be unequal.
+    /// it is not always possible to determine inequality of two pointers, so this function may
+    /// spuriously return `None` for pointers that later actually turn out to have its inequality known.
+    /// But when it returns `Some`, the pointers' inequality is guaranteed to be known.
     ///
-    /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
-    /// comparisons for which both functions return `false`.
-    ///
-    /// [`guaranteed_eq`]: #method.guaranteed_eq
-    ///
-    /// The return value may change depending on the compiler version and unsafe code must not
+    /// The return value may change from `Some` to `None` and vice versa depending on the compiler
+    /// version and unsafe code must not
     /// rely on the result of this function for soundness. It is suggested to only use this function
-    /// for performance optimizations where spurious `false` return values by this function do not
+    /// for performance optimizations where spurious `None` return values by this function do not
     /// affect the outcome, but just the performance.
     /// The consequences of using this method to make runtime and compile-time code behave
     /// differently have not been explored. This method should not be used to introduce such
@@ -823,11 +821,14 @@ impl<T: ?Sized> *const T {
     #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[inline]
-    pub const fn guaranteed_ne(self, other: *const T) -> bool
+    pub const fn guaranteed_ne(self, other: *const T) -> Option<bool>
     where
         T: Sized,
     {
-        intrinsics::ptr_guaranteed_ne(self, other)
+        match self.guaranteed_eq(other) {
+            None => None,
+            Some(eq) => Some(!eq),
+        }
     }
 
     /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 3e4c3ae0756..460f3df5fee 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -35,7 +35,10 @@ impl<T: ?Sized> *mut T {
     pub const fn is_null(self) -> bool {
         // Compare via a cast to a thin pointer, so fat pointers are only
         // considering their "data" part for null-ness.
-        (self as *mut u8).guaranteed_eq(null_mut())
+        match (self as *mut u8).guaranteed_eq(null_mut()) {
+            None => false,
+            Some(res) => res,
+        }
     }
 
     /// Casts to a pointer of another type.
@@ -697,20 +700,16 @@ impl<T: ?Sized> *mut T {
 
     /// Returns whether two pointers are guaranteed to be equal.
     ///
-    /// At runtime this function behaves like `self == other`.
+    /// At runtime this function behaves like `Some(self == other)`.
     /// However, in some contexts (e.g., compile-time evaluation),
     /// it is not always possible to determine equality of two pointers, so this function may
-    /// spuriously return `false` for pointers that later actually turn out to be equal.
-    /// But when it returns `true`, the pointers are guaranteed to be equal.
-    ///
-    /// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer
-    /// comparisons for which both functions return `false`.
-    ///
-    /// [`guaranteed_ne`]: #method.guaranteed_ne
+    /// spuriously return `None` for pointers that later actually turn out to have its equality known.
+    /// But when it returns `Some`, the pointers' equality is guaranteed to be known.
     ///
-    /// The return value may change depending on the compiler version and unsafe code might not
+    /// The return value may change from `Some` to `None` and vice versa depending on the compiler
+    /// version and unsafe code must not
     /// rely on the result of this function for soundness. It is suggested to only use this function
-    /// for performance optimizations where spurious `false` return values by this function do not
+    /// for performance optimizations where spurious `None` return values by this function do not
     /// affect the outcome, but just the performance.
     /// The consequences of using this method to make runtime and compile-time code behave
     /// differently have not been explored. This method should not be used to introduce such
@@ -719,29 +718,25 @@ impl<T: ?Sized> *mut T {
     #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[inline]
-    pub const fn guaranteed_eq(self, other: *mut T) -> bool
+    pub const fn guaranteed_eq(self, other: *mut T) -> Option<bool>
     where
         T: Sized,
     {
-        intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _)
+        (self as *const T).guaranteed_eq(other as _)
     }
 
-    /// Returns whether two pointers are guaranteed to be unequal.
+    /// Returns whether two pointers are guaranteed to be inequal.
     ///
-    /// At runtime this function behaves like `self != other`.
+    /// At runtime this function behaves like `Some(self == other)`.
     /// However, in some contexts (e.g., compile-time evaluation),
-    /// it is not always possible to determine the inequality of two pointers, so this function may
-    /// spuriously return `false` for pointers that later actually turn out to be unequal.
-    /// But when it returns `true`, the pointers are guaranteed to be unequal.
-    ///
-    /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
-    /// comparisons for which both functions return `false`.
-    ///
-    /// [`guaranteed_eq`]: #method.guaranteed_eq
+    /// it is not always possible to determine inequality of two pointers, so this function may
+    /// spuriously return `None` for pointers that later actually turn out to have its inequality known.
+    /// But when it returns `Some`, the pointers' inequality is guaranteed to be known.
     ///
-    /// The return value may change depending on the compiler version and unsafe code might not
+    /// The return value may change from `Some` to `None` and vice versa depending on the compiler
+    /// version and unsafe code must not
     /// rely on the result of this function for soundness. It is suggested to only use this function
-    /// for performance optimizations where spurious `false` return values by this function do not
+    /// for performance optimizations where spurious `None` return values by this function do not
     /// affect the outcome, but just the performance.
     /// The consequences of using this method to make runtime and compile-time code behave
     /// differently have not been explored. This method should not be used to introduce such
@@ -750,11 +745,11 @@ impl<T: ?Sized> *mut T {
     #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
     #[inline]
-    pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool
+    pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
     where
         T: Sized,
     {
-        intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _)
+        (self as *const T).guaranteed_ne(other as _)
     }
 
     /// Calculates the distance between two pointers. The returned value is in
diff --git a/src/test/ui/consts/miri_unleashed/slice_eq.rs b/src/test/ui/consts/miri_unleashed/slice_eq.rs
index fd843105daf..83e10bf1213 100644
--- a/src/test/ui/consts/miri_unleashed/slice_eq.rs
+++ b/src/test/ui/consts/miri_unleashed/slice_eq.rs
@@ -4,14 +4,10 @@
 #![feature(const_raw_ptr_comparison)]
 
 const EMPTY_SLICE: &[i32] = &[];
-const EMPTY_EQ: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[] as *const _);
-const EMPTY_EQ2: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[] as *const _);
-const EMPTY_NE: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[1] as *const _);
-const EMPTY_NE2: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[1] as *const _);
+const EMPTY_EQ: Option<bool> = EMPTY_SLICE.as_ptr().guaranteed_eq(&[] as *const _);
+const EMPTY_EQ2: Option<bool> = EMPTY_SLICE.as_ptr().guaranteed_eq(&[1] as *const _);
 
 fn main() {
-    assert!(!EMPTY_EQ);
-    assert!(!EMPTY_EQ2);
-    assert!(!EMPTY_NE);
-    assert!(!EMPTY_NE2);
+    assert!(EMPTY_EQ.is_none());
+    assert!(EMPTY_EQ2.is_none());
 }
diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs
index 20233db09c9..0a3c2d4bedc 100644
--- a/src/test/ui/consts/ptr_comparisons.rs
+++ b/src/test/ui/consts/ptr_comparisons.rs
@@ -14,38 +14,30 @@ const FOO: &usize = &42;
 macro_rules! check {
     (eq, $a:expr, $b:expr) => {
         pub const _: () =
-            assert!(std::intrinsics::ptr_guaranteed_eq($a as *const u8, $b as *const u8));
+            assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 1);
     };
     (ne, $a:expr, $b:expr) => {
         pub const _: () =
-            assert!(std::intrinsics::ptr_guaranteed_ne($a as *const u8, $b as *const u8));
+            assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 0);
     };
-    (!eq, $a:expr, $b:expr) => {
+    (!, $a:expr, $b:expr) => {
         pub const _: () =
-            assert!(!std::intrinsics::ptr_guaranteed_eq($a as *const u8, $b as *const u8));
-    };
-    (!ne, $a:expr, $b:expr) => {
-        pub const _: () =
-            assert!(!std::intrinsics::ptr_guaranteed_ne($a as *const u8, $b as *const u8));
+            assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 2);
     };
 }
 
 check!(eq, 0, 0);
 check!(ne, 0, 1);
-check!(!eq, 0, 1);
-check!(!ne, 0, 0);
 check!(ne, FOO as *const _, 0);
-check!(!eq, FOO as *const _, 0);
+check!(ne, unsafe { (FOO as *const usize).offset(1) }, 0);
+check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0);
+
 // We want pointers to be equal to themselves, but aren't checking this yet because
 // there are some open questions (e.g. whether function pointers to the same function
 // compare equal, they don't necessarily at runtime).
 // The case tested here should work eventually, but does not work yet.
-check!(!eq, FOO as *const _, FOO as *const _);
-check!(ne, unsafe { (FOO as *const usize).offset(1) }, 0);
-check!(!eq, unsafe { (FOO as *const usize).offset(1) }, 0);
+check!(!, FOO as *const _, FOO as *const _);
 
-check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0);
-check!(!eq, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0);
 
 ///////////////////////////////////////////////////////////////////////////////
 // If any of the below start compiling, make sure to add a `check` test for it.
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
index 1d47f243f01..3de2aba5b05 100644
--- a/src/test/ui/consts/ptr_comparisons.stderr
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -7,19 +7,19 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/ptr_comparisons.rs:58:34
+  ::: $DIR/ptr_comparisons.rs:50:34
    |
 LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
-   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:58:34
+   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:50:34
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ptr_comparisons.rs:61:33
+  --> $DIR/ptr_comparisons.rs:53:33
    |
 LL |     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds
 
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:65:27
+  --> $DIR/ptr_comparisons.rs:57:27
    |
 LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
    | --------------            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -31,7 +31,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) +
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:70:27
+  --> $DIR/ptr_comparisons.rs:62:27
    |
 LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
    | --------------            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -46,7 +46,7 @@ error: aborting due to 4 previous errors
 For more information about this error, try `rustc --explain E0080`.
 Future incompatibility report: Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:65:27
+  --> $DIR/ptr_comparisons.rs:57:27
    |
 LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
    | --------------            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -59,7 +59,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) +
 
 Future breakage diagnostic:
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:70:27
+  --> $DIR/ptr_comparisons.rs:62:27
    |
 LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
    | --------------            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes