From d42d678724d6ce6435f3db8b4a4163dc17497d43 Mon Sep 17 00:00:00 2001 From: Aria Beingessner Date: Sat, 2 Mar 2024 19:13:31 -0500 Subject: [PATCH] feat(byte_sub_ptr): add ptr::byte_sub_ptr This is an API that naturally should exist as a combination of byte_offset_from and sub_ptr both existing (they showed up at similar times so this union was never made). Adding these is a logical (and perhaps final) precondition of stabilizing ptr_sub_ptr (#95892). --- library/core/src/ptr/const_ptr.rs | 19 +++++++++++++++++++ library/core/src/ptr/mut_ptr.rs | 19 +++++++++++++++++++ library/core/src/ptr/non_null.rs | 19 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 85a56d37ab75c..8872aed6eb89d 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -824,6 +824,25 @@ impl *const T { unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) } } + /// Calculates the distance between two pointers, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub_ptr`][pointer::sub_ptr] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub_ptr(self, origin: *const U) -> usize { + // SAFETY: the caller must uphold the safety contract for `sub_ptr`. + unsafe { self.cast::().sub_ptr(origin.cast::()) } + } + /// Returns whether two pointers are guaranteed to be equal. /// /// At runtime this function behaves like `Some(self == other)`. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 28ba26f5c16c4..f9eaae0195d98 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -984,6 +984,25 @@ impl *mut T { unsafe { (self as *const T).sub_ptr(origin) } } + /// Calculates the distance between two pointers, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub_ptr`][pointer::sub_ptr] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[unstable(feature = "ptr_sub_ptr", issue = "95892")] + #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub_ptr(self, origin: *mut U) -> usize { + // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`. + unsafe { (self as *const T).byte_sub_ptr(origin) } + } + /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index acb8c552a6338..4993dcf91c61b 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -957,6 +957,25 @@ impl NonNull { unsafe { self.pointer.sub_ptr(subtracted.pointer) } } + /// Calculates the distance between two pointers, *where it's known that + /// `self` is equal to or greater than `origin`*. The returned value is in + /// units of **bytes**. + /// + /// This is purely a convenience for casting to a `u8` pointer and + /// using [`sub_ptr`][NonNull::sub_ptr] on it. See that method for + /// documentation and safety requirements. + /// + /// For non-`Sized` pointees this operation considers only the data pointers, + /// ignoring the metadata. + #[unstable(feature = "non_null_convenience", issue = "117691")] + #[rustc_const_unstable(feature = "non_null_convenience", issue = "117691")] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces + pub const unsafe fn byte_sub_ptr(self, origin: NonNull) -> usize { + // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`. + unsafe { self.pointer.byte_sub_ptr(origin.pointer) } + } + /// Reads the value from `self` without moving it. This leaves the /// memory in `self` unchanged. ///