about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/intrinsics.rs16
-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.rs17
5 files changed, 163 insertions, 3 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 9061145a695..50e321f9c71 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1012,7 +1012,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::any::type_name`](../../std/any/fn.type_name.html)
-    #[rustc_const_unstable(feature = "const_type_name", issue = "none")]
+    #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
     pub fn type_name<T: ?Sized>() -> &'static str;
 
     /// Gets an identifier which is globally unique to the specified type. This
@@ -1021,7 +1021,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of)
-    #[rustc_const_unstable(feature = "const_type_id", issue = "none")]
+    #[rustc_const_unstable(feature = "const_type_id", issue = "41875")]
     pub fn type_id<T: ?Sized + 'static>() -> u64;
 
     /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
@@ -1931,7 +1931,7 @@ extern "rust-intrinsic" {
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
 
     /// See documentation of `<*const T>::offset_from` for details.
-    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "none")]
+    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
     /// Internal hook used by Miri to implement unwinding.
@@ -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 0115c4df2fd..4eb2fdbd078 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 acc09ddc014..395b3879cfd 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 to be 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 to be inequal.
+    ///
+    /// 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 2bbeb95965e..b86ef5b13b3 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 to be 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 to be inequal.
+    ///
+    /// 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..c69aafe687c 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -5956,10 +5956,18 @@ where
             return false;
         }
 
+        #[cfg(bootstrap)]
         if self.as_ptr() == other.as_ptr() {
             return true;
         }
 
+        // While performance would suffer if `guaranteed_eq` just returned `false`
+        // for all arguments, correctness and return value of this function are not affected.
+        #[cfg(not(bootstrap))]
+        if self.as_ptr().guaranteed_eq(other.as_ptr()) {
+            return true;
+        }
+
         self.iter().zip(other.iter()).all(|(x, y)| x == y)
     }
 }
@@ -5973,9 +5981,18 @@ where
         if self.len() != other.len() {
             return false;
         }
+
+        #[cfg(bootstrap)]
         if self.as_ptr() == other.as_ptr() {
             return true;
         }
+
+        // While performance would suffer if `guaranteed_eq` just returned `false`
+        // for all arguments, correctness and return value of this function are not affected.
+        #[cfg(not(bootstrap))]
+        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