Skip to content

Commit 27950d3

Browse files
committed
The <*const T>::guaranteed_* methods now return an option for the unknown case
1 parent b229bc7 commit 27950d3

File tree

3 files changed

+69
-60
lines changed

3 files changed

+69
-60
lines changed

core/src/intrinsics.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,21 +2013,24 @@ extern "rust-intrinsic" {
20132013
pub fn ptr_offset_from_unsigned<T>(ptr: *const T, base: *const T) -> usize;
20142014

20152015
/// See documentation of `<*const T>::guaranteed_eq` for details.
2016+
/// Returns `2` if the result is unknown.
2017+
/// Returns `1` if the pointers are guaranteed equal
2018+
/// Returns `0` if the pointers are guaranteed inequal
20162019
///
20172020
/// Note that, unlike most intrinsics, this is safe to call;
20182021
/// it does not require an `unsafe` block.
20192022
/// Therefore, implementations must not require the user to uphold
20202023
/// any safety invariants.
20212024
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
2025+
#[cfg(not(bootstrap))]
2026+
pub fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8;
2027+
2028+
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
2029+
#[cfg(bootstrap)]
20222030
pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
20232031

2024-
/// See documentation of `<*const T>::guaranteed_ne` for details.
2025-
///
2026-
/// Note that, unlike most intrinsics, this is safe to call;
2027-
/// it does not require an `unsafe` block.
2028-
/// Therefore, implementations must not require the user to uphold
2029-
/// any safety invariants.
20302032
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
2033+
#[cfg(bootstrap)]
20312034
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
20322035

20332036
/// 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) -
22132216
diff >= size
22142217
}
22152218

2219+
#[cfg(bootstrap)]
2220+
pub const fn ptr_guaranteed_cmp(a: *const (), b: *const ()) -> u8 {
2221+
match (ptr_guaranteed_eq(a, b), ptr_guaranteed_ne(a, b)) {
2222+
(false, false) => 2,
2223+
(true, false) => 1,
2224+
(false, true) => 0,
2225+
(true, true) => unreachable!(),
2226+
}
2227+
}
2228+
22162229
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
22172230
/// and destination must *not* overlap.
22182231
///

core/src/ptr/const_ptr.rs

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ impl<T: ?Sized> *const T {
3636
pub const fn is_null(self) -> bool {
3737
// Compare via a cast to a thin pointer, so fat pointers are only
3838
// considering their "data" part for null-ness.
39-
(self as *const u8).guaranteed_eq(null())
39+
match (self as *const u8).guaranteed_eq(null()) {
40+
None => false,
41+
Some(res) => res,
42+
}
4043
}
4144

4245
/// Casts to a pointer of another type.
@@ -770,20 +773,16 @@ impl<T: ?Sized> *const T {
770773

771774
/// Returns whether two pointers are guaranteed to be equal.
772775
///
773-
/// At runtime this function behaves like `self == other`.
776+
/// At runtime this function behaves like `Some(self == other)`.
774777
/// However, in some contexts (e.g., compile-time evaluation),
775778
/// it is not always possible to determine equality of two pointers, so this function may
776-
/// spuriously return `false` for pointers that later actually turn out to be equal.
777-
/// But when it returns `true`, the pointers are guaranteed to be equal.
778-
///
779-
/// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer
780-
/// comparisons for which both functions return `false`.
779+
/// spuriously return `None` for pointers that later actually turn out to have its equality known.
780+
/// But when it returns `Some`, the pointers' equality is guaranteed to be known.
781781
///
782-
/// [`guaranteed_ne`]: #method.guaranteed_ne
783-
///
784-
/// The return value may change depending on the compiler version and unsafe code must not
782+
/// The return value may change from `Some` to `None` and vice versa depending on the compiler
783+
/// version and unsafe code must not
785784
/// rely on the result of this function for soundness. It is suggested to only use this function
786-
/// for performance optimizations where spurious `false` return values by this function do not
785+
/// for performance optimizations where spurious `None` return values by this function do not
787786
/// affect the outcome, but just the performance.
788787
/// The consequences of using this method to make runtime and compile-time code behave
789788
/// differently have not been explored. This method should not be used to introduce such
@@ -792,29 +791,28 @@ impl<T: ?Sized> *const T {
792791
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
793792
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
794793
#[inline]
795-
pub const fn guaranteed_eq(self, other: *const T) -> bool
794+
pub const fn guaranteed_eq(self, other: *const T) -> Option<bool>
796795
where
797796
T: Sized,
798797
{
799-
intrinsics::ptr_guaranteed_eq(self, other)
798+
match intrinsics::ptr_guaranteed_cmp(self as _, other as _) {
799+
2 => None,
800+
other => Some(other == 1),
801+
}
800802
}
801803

802-
/// Returns whether two pointers are guaranteed to be unequal.
804+
/// Returns whether two pointers are guaranteed to be inequal.
803805
///
804-
/// At runtime this function behaves like `self != other`.
806+
/// At runtime this function behaves like `Some(self == other)`.
805807
/// However, in some contexts (e.g., compile-time evaluation),
806-
/// it is not always possible to determine the inequality of two pointers, so this function may
807-
/// spuriously return `false` for pointers that later actually turn out to be unequal.
808-
/// But when it returns `true`, the pointers are guaranteed to be unequal.
808+
/// it is not always possible to determine inequality of two pointers, so this function may
809+
/// spuriously return `None` for pointers that later actually turn out to have its inequality known.
810+
/// But when it returns `Some`, the pointers' inequality is guaranteed to be known.
809811
///
810-
/// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
811-
/// comparisons for which both functions return `false`.
812-
///
813-
/// [`guaranteed_eq`]: #method.guaranteed_eq
814-
///
815-
/// The return value may change depending on the compiler version and unsafe code must not
812+
/// The return value may change from `Some` to `None` and vice versa depending on the compiler
813+
/// version and unsafe code must not
816814
/// rely on the result of this function for soundness. It is suggested to only use this function
817-
/// for performance optimizations where spurious `false` return values by this function do not
815+
/// for performance optimizations where spurious `None` return values by this function do not
818816
/// affect the outcome, but just the performance.
819817
/// The consequences of using this method to make runtime and compile-time code behave
820818
/// differently have not been explored. This method should not be used to introduce such
@@ -823,11 +821,14 @@ impl<T: ?Sized> *const T {
823821
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
824822
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
825823
#[inline]
826-
pub const fn guaranteed_ne(self, other: *const T) -> bool
824+
pub const fn guaranteed_ne(self, other: *const T) -> Option<bool>
827825
where
828826
T: Sized,
829827
{
830-
intrinsics::ptr_guaranteed_ne(self, other)
828+
match self.guaranteed_eq(other) {
829+
None => None,
830+
Some(eq) => Some(!eq),
831+
}
831832
}
832833

833834
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).

core/src/ptr/mut_ptr.rs

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ impl<T: ?Sized> *mut T {
3535
pub const fn is_null(self) -> bool {
3636
// Compare via a cast to a thin pointer, so fat pointers are only
3737
// considering their "data" part for null-ness.
38-
(self as *mut u8).guaranteed_eq(null_mut())
38+
match (self as *mut u8).guaranteed_eq(null_mut()) {
39+
None => false,
40+
Some(res) => res,
41+
}
3942
}
4043

4144
/// Casts to a pointer of another type.
@@ -697,20 +700,16 @@ impl<T: ?Sized> *mut T {
697700

698701
/// Returns whether two pointers are guaranteed to be equal.
699702
///
700-
/// At runtime this function behaves like `self == other`.
703+
/// At runtime this function behaves like `Some(self == other)`.
701704
/// However, in some contexts (e.g., compile-time evaluation),
702705
/// it is not always possible to determine equality of two pointers, so this function may
703-
/// spuriously return `false` for pointers that later actually turn out to be equal.
704-
/// But when it returns `true`, the pointers are guaranteed to be equal.
705-
///
706-
/// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer
707-
/// comparisons for which both functions return `false`.
708-
///
709-
/// [`guaranteed_ne`]: #method.guaranteed_ne
706+
/// spuriously return `None` for pointers that later actually turn out to have its equality known.
707+
/// But when it returns `Some`, the pointers' equality is guaranteed to be known.
710708
///
711-
/// The return value may change depending on the compiler version and unsafe code might not
709+
/// The return value may change from `Some` to `None` and vice versa depending on the compiler
710+
/// version and unsafe code must not
712711
/// rely on the result of this function for soundness. It is suggested to only use this function
713-
/// for performance optimizations where spurious `false` return values by this function do not
712+
/// for performance optimizations where spurious `None` return values by this function do not
714713
/// affect the outcome, but just the performance.
715714
/// The consequences of using this method to make runtime and compile-time code behave
716715
/// differently have not been explored. This method should not be used to introduce such
@@ -719,29 +718,25 @@ impl<T: ?Sized> *mut T {
719718
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
720719
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
721720
#[inline]
722-
pub const fn guaranteed_eq(self, other: *mut T) -> bool
721+
pub const fn guaranteed_eq(self, other: *mut T) -> Option<bool>
723722
where
724723
T: Sized,
725724
{
726-
intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _)
725+
(self as *const T).guaranteed_eq(other as _)
727726
}
728727

729-
/// Returns whether two pointers are guaranteed to be unequal.
728+
/// Returns whether two pointers are guaranteed to be inequal.
730729
///
731-
/// At runtime this function behaves like `self != other`.
730+
/// At runtime this function behaves like `Some(self == other)`.
732731
/// However, in some contexts (e.g., compile-time evaluation),
733-
/// it is not always possible to determine the inequality of two pointers, so this function may
734-
/// spuriously return `false` for pointers that later actually turn out to be unequal.
735-
/// But when it returns `true`, the pointers are guaranteed to be unequal.
736-
///
737-
/// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
738-
/// comparisons for which both functions return `false`.
739-
///
740-
/// [`guaranteed_eq`]: #method.guaranteed_eq
732+
/// it is not always possible to determine inequality of two pointers, so this function may
733+
/// spuriously return `None` for pointers that later actually turn out to have its inequality known.
734+
/// But when it returns `Some`, the pointers' inequality is guaranteed to be known.
741735
///
742-
/// The return value may change depending on the compiler version and unsafe code might not
736+
/// The return value may change from `Some` to `None` and vice versa depending on the compiler
737+
/// version and unsafe code must not
743738
/// rely on the result of this function for soundness. It is suggested to only use this function
744-
/// for performance optimizations where spurious `false` return values by this function do not
739+
/// for performance optimizations where spurious `None` return values by this function do not
745740
/// affect the outcome, but just the performance.
746741
/// The consequences of using this method to make runtime and compile-time code behave
747742
/// differently have not been explored. This method should not be used to introduce such
@@ -750,11 +745,11 @@ impl<T: ?Sized> *mut T {
750745
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
751746
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
752747
#[inline]
753-
pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool
748+
pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
754749
where
755750
T: Sized,
756751
{
757-
intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _)
752+
(self as *const T).guaranteed_ne(other as _)
758753
}
759754

760755
/// Calculates the distance between two pointers. The returned value is in

0 commit comments

Comments
 (0)