diff options
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/intrinsics.rs | 16 | ||||
| -rw-r--r-- | src/libcore/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcore/ptr/const_ptr.rs | 66 | ||||
| -rw-r--r-- | src/libcore/ptr/mut_ptr.rs | 66 | ||||
| -rw-r--r-- | src/libcore/slice/mod.rs | 17 |
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 |
