about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2020-06-16 10:37:34 +0200
committerOliver Scherer <github35764891676564198441@oli-obk.de>2020-06-19 18:13:41 +0200
commite09b62033926dff8bfedca35b93e0dfbf767749f (patch)
treeb7002d10c8dce99dfd2ac5551f057bdd982db090 /src
parent9245ba83047b14fc7c9cef4c7d2bf37828c445b6 (diff)
downloadrust-e09b62033926dff8bfedca35b93e0dfbf767749f.tar.gz
rust-e09b62033926dff8bfedca35b93e0dfbf767749f.zip
Add fuzzy pointer comparison intrinsics
Diffstat (limited to 'src')
-rw-r--r--src/libcore/intrinsics.rs10
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/ptr/const_ptr.rs66
-rw-r--r--src/libcore/ptr/mut_ptr.rs66
-rw-r--r--src/libcore/slice/mod.rs50
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs14
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs5
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs22
-rw-r--r--src/librustc_span/symbol.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs9
-rw-r--r--src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr10
-rw-r--r--src/test/ui/consts/miri_unleashed/slice_eq.rs17
-rw-r--r--src/test/ui/error-codes/E0395.stderr5
-rw-r--r--src/test/ui/issues/issue-25826.stderr5
14 files changed, 260 insertions, 22 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 9061145a695..4648f762bab 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1948,6 +1948,16 @@ extern "rust-intrinsic" {
     #[cfg(not(bootstrap))]
     #[lang = "count_code_region"]
     pub fn count_code_region(index: u32);
+
+    /// See documentation of `<*const T>::guaranteed_eq` for details.
+    #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[cfg(not(bootstrap))]
+    pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
+
+    /// See documentation of `<*const T>::guaranteed_ne` for details.
+    #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[cfg(not(bootstrap))]
+    pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
 }
 
 // Some functions are defined here because they accidentally got made
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index fe05e914e6d..b2f6f789603 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -87,6 +87,7 @@
 #![feature(const_generics)]
 #![feature(const_ptr_offset)]
 #![feature(const_ptr_offset_from)]
+#![cfg_attr(not(bootstrap), feature(const_raw_ptr_comparison))]
 #![feature(const_result)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_slice_ptr_len)]
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
index e39d18d7733..0e2e6848416 100644
--- a/src/libcore/ptr/const_ptr.rs
+++ b/src/libcore/ptr/const_ptr.rs
@@ -295,6 +295,72 @@ impl<T: ?Sized> *const T {
         intrinsics::ptr_offset_from(self, origin)
     }
 
+    /// Returns whether two pointers are guaranteed equal.
+    ///
+    /// At runtime this function behaves like `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
+    ///
+    /// The return value may change depending on the compiler version and unsafe code may 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
+    /// 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
+    /// differences, and it should also not be stabilized before we have a better understanding
+    /// of this issue.
+    /// ```
+    #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[inline]
+    #[cfg(not(bootstrap))]
+    pub const fn guaranteed_eq(self, other: *const T) -> bool
+    where
+        T: Sized,
+    {
+        intrinsics::ptr_guaranteed_eq(self, other)
+    }
+
+    /// Returns whether two pointers are guaranteed not equal.
+    ///
+    /// At runtime this function behaves like `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 inequal.
+    /// But when it returns `true`, the pointers are guaranteed to be inequal.
+    ///
+    /// 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 may 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
+    /// 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
+    /// differences, and it should also not be stabilized before we have a better understanding
+    /// of this issue.
+    /// ```
+    #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[inline]
+    #[cfg(not(bootstrap))]
+    pub const fn guaranteed_ne(self, other: *const T) -> bool
+    where
+        T: Sized,
+    {
+        intrinsics::ptr_guaranteed_ne(self, other)
+    }
+
     /// Calculates the distance between two pointers. The returned value is in
     /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
     ///
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
index 40b5e4e2234..67ace1f72a0 100644
--- a/src/libcore/ptr/mut_ptr.rs
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -273,6 +273,72 @@ impl<T: ?Sized> *mut T {
         if self.is_null() { None } else { Some(&mut *self) }
     }
 
+    /// Returns whether two pointers are guaranteed equal.
+    ///
+    /// At runtime this function behaves like `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
+    ///
+    /// The return value may change depending on the compiler version and unsafe code may 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
+    /// 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
+    /// differences, and it should also not be stabilized before we have a better understanding
+    /// of this issue.
+    /// ```
+    #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[inline]
+    #[cfg(not(bootstrap))]
+    pub const fn guaranteed_eq(self, other: *mut T) -> bool
+    where
+        T: Sized,
+    {
+        intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _)
+    }
+
+    /// Returns whether two pointers are guaranteed not equal.
+    ///
+    /// At runtime this function behaves like `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 inequal.
+    /// But when it returns `true`, the pointers are guaranteed to be inequal.
+    ///
+    /// 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 may 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
+    /// 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
+    /// differences, and it should also not be stabilized before we have a better understanding
+    /// of this issue.
+    /// ```
+    #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
+    #[inline]
+    #[cfg(not(bootstrap))]
+    pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool
+    where
+        T: Sized,
+    {
+        intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _)
+    }
+
     /// Calculates the distance between two pointers. The returned value is in
     /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
     ///
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 21ba2b5abcf..12932b06d32 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -5946,7 +5946,8 @@ where
     }
 }
 
-// Use an equal-pointer optimization when types are `Eq`
+// Remove after boostrap bump
+#[cfg(bootstrap)]
 impl<A> SlicePartialEq<A> for [A]
 where
     A: PartialEq<A> + Eq,
@@ -5964,7 +5965,8 @@ where
     }
 }
 
-// Use memcmp for bytewise equality when the types allow
+// Remove after boostrap bump
+#[cfg(bootstrap)]
 impl<A> SlicePartialEq<A> for [A]
 where
     A: PartialEq<A> + BytewiseEquality,
@@ -5983,6 +5985,50 @@ where
     }
 }
 
+// Use an equal-pointer optimization when types are `Eq`
+#[cfg(not(bootstrap))]
+impl<A> SlicePartialEq<A> for [A]
+where
+    A: PartialEq<A> + Eq,
+{
+    default fn equal(&self, other: &[A]) -> bool {
+        if self.len() != other.len() {
+            return false;
+        }
+
+        // While performance would suffer if `guaranteed_eq` just returned `false`
+        // for all arguments, correctness and return value of this function are not affected.
+        if self.as_ptr().guaranteed_eq(other.as_ptr()) {
+            return true;
+        }
+
+        self.iter().zip(other.iter()).all(|(x, y)| x == y)
+    }
+}
+
+// Use memcmp for bytewise equality when the types allow
+#[cfg(not(bootstrap))]
+impl<A> SlicePartialEq<A> for [A]
+where
+    A: PartialEq<A> + BytewiseEquality,
+{
+    fn equal(&self, other: &[A]) -> bool {
+        if self.len() != other.len() {
+            return false;
+        }
+
+        // While performance would suffer if `guaranteed_eq` just returned `false`
+        // for all arguments, correctness and return value of this function are not affected.
+        if self.as_ptr().guaranteed_eq(other.as_ptr()) {
+            return true;
+        }
+        unsafe {
+            let size = mem::size_of_val(self);
+            memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0
+        }
+    }
+}
+
 #[doc(hidden)]
 // intermediate trait for specialization of slice's PartialOrd
 trait SlicePartialOrd: Sized {
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 95465939070..78c29588e2e 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -12,7 +12,7 @@ use log::debug;
 use rustc_ast::ast;
 use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
 use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
-use rustc_codegen_ssa::common::TypeKind;
+use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::glue;
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
@@ -731,6 +731,18 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                 return;
             }
 
+            "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => {
+                let a = args[0].immediate();
+                let b = args[1].immediate();
+                let a = self.ptrtoint(a, self.type_isize());
+                let b = self.ptrtoint(b, self.type_isize());
+                if name == "ptr_guaranteed_eq" {
+                    self.icmp(IntPredicate::IntEQ, a, b)
+                } else {
+                    self.icmp(IntPredicate::IntNE, a, b)
+                }
+            }
+
             "ptr_offset_from" => {
                 let ty = substs.type_at(0);
                 let pointee_size = self.size_of(ty);
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index ac28ccd1815..1b4113a61b4 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -291,6 +291,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self);
                 self.write_scalar(offset_ptr, dest)?;
             }
+            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
+                // FIXME: return `true` for at least some comparisons where we can reliably
+                // determine the result of runtime (in)equality tests at compile-time.
+                self.write_scalar(Scalar::from_bool(false), dest)?;
+            }
             sym::ptr_offset_from => {
                 let a = self.read_immediate(args[0])?.to_scalar()?;
                 let b = self.read_immediate(args[1])?.to_scalar()?;
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index f09b598ce06..9f005c0b4dd 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -290,17 +290,23 @@ impl NonConstOp for RawPtrComparison {
             "pointers cannot be compared in a meaningful way during const eval.",
         );
         err.note(
-            "It is conceptually impossible for const eval to know in all cases whether two \
-             pointers are equal. While sometimes it is clear (the address of a static item \
-             is never equal to the address of another static item), comparing an integer \
-             address with any allocation's address is impossible to do at compile-time.",
+            "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> \
+            for more information",
         );
         err.note(
-            "That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all \
-             comparisons where CTFE isn't sure whether two addresses are equal. The mirror \
-             intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't \
-             sure whether two addresses are inequal.",
+            "It is conceptually impossible for const eval to know in all cases whether two \
+             pointers are equal. While sometimes it is clear (the address of a non-zst static item \
+             is never equal to the address of another non-zst static item), comparing an integer \
+             address with any allocation's address is impossible to do at compile-time.",
         );
+        if ccx.tcx.sess.parse_sess.unstable_features.is_nightly_build() {
+            err.note(
+                "That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` \
+                for all comparisons where CTFE is sure that two addresses are equal. The mirror \
+                intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where \
+                CTFE is sure that two addresses are inequal.",
+            );
+        }
         err.emit();
     }
 }
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 970a2632592..06d1f36622b 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -588,6 +588,8 @@ symbols! {
         proc_macro_non_items,
         proc_macro_path_invoc,
         profiler_runtime,
+        ptr_guaranteed_eq,
+        ptr_guaranteed_ne,
         ptr_offset_from,
         pub_restricted,
         pure,
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 3ec6973a17d..ef6c7c14404 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -74,9 +74,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
         | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
         | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
         | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely"
-        | "minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64" | "type_name" => {
-            hir::Unsafety::Normal
-        }
+        | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32"
+        | "maxnumf64" | "type_name" => hir::Unsafety::Normal,
         _ => hir::Unsafety::Unsafe,
     }
 }
@@ -258,6 +257,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
             }
 
+            "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => {
+                (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool)
+            }
+
             "ptr_offset_from" => {
                 (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
             }
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
index dee555beca0..6f27ac74ade 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
@@ -4,8 +4,9 @@ error: pointers cannot be compared in a meaningful way during const eval.
 LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
-   = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal.
+   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
+   = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal.
 
 error: pointers cannot be compared in a meaningful way during const eval.
   --> $DIR/const_raw_ptr_ops.rs:6:27
@@ -13,8 +14,9 @@ error: pointers cannot be compared in a meaningful way during const eval.
 LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
-   = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal.
+   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
+   = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal.
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/miri_unleashed/slice_eq.rs b/src/test/ui/consts/miri_unleashed/slice_eq.rs
new file mode 100644
index 00000000000..fd843105daf
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/slice_eq.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+// run-pass
+
+#![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 _);
+
+fn main() {
+    assert!(!EMPTY_EQ);
+    assert!(!EMPTY_EQ2);
+    assert!(!EMPTY_NE);
+    assert!(!EMPTY_NE2);
+}
diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr
index 748126f7440..62949cf15e1 100644
--- a/src/test/ui/error-codes/E0395.stderr
+++ b/src/test/ui/error-codes/E0395.stderr
@@ -4,8 +4,9 @@ error: pointers cannot be compared in a meaningful way during const eval.
 LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
-   = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal.
+   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
+   = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal.
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr
index b3692098341..cb24aede81a 100644
--- a/src/test/ui/issues/issue-25826.stderr
+++ b/src/test/ui/issues/issue-25826.stderr
@@ -4,8 +4,9 @@ error: pointers cannot be compared in a meaningful way during const eval.
 LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a static item is never equal to the address of another static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
-   = note: That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all comparisons where CTFE isn't sure whether two addresses are equal. The mirror intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't sure whether two addresses are inequal.
+   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = note: It is conceptually impossible for const eval to know in all cases whether two pointers are equal. While sometimes it is clear (the address of a non-zst static item is never equal to the address of another non-zst static item), comparing an integer address with any allocation's address is impossible to do at compile-time.
+   = note: That said, there's the `<*const T>::guaranteed_eq` intrinsic which returns `true` for all comparisons where CTFE is sure that two addresses are equal. The mirror intrinsic `<*const T>::guaranteed_ne` returns `true` for all comparisons where CTFE is sure that two addresses are inequal.
 
 error: aborting due to previous error