Rollup merge of #132459 - RalfJung:byte_sub_ptr, r=scottmcm

feat(byte_sub_ptr): unstably 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 (https://github.com/rust-lang/rust/issues/95892).

Original PR by ``@Gankra`` (https://github.com/rust-lang/rust/pull/121919), I am just reviving it. The 2nd commit (with a small docs tweak) is by me.
This commit is contained in:
Guillaume Gomez 2024-11-02 03:08:56 +08:00 committed by GitHub
commit 305ca05cbe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 66 additions and 9 deletions

View File

@ -582,7 +582,7 @@ pub fn mask(self, mask: usize) -> *const T {
intrinsics::ptr_mask(self.cast::<()>(), mask).with_metadata_of(self)
}
/// Calculates the distance between two pointers. The returned value is in
/// Calculates the distance between two pointers within the same allocation. The returned value is in
/// units of T: the distance in bytes divided by `mem::size_of::<T>()`.
///
/// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::<T>() as isize)`,
@ -677,7 +677,7 @@ pub fn mask(self, mask: usize) -> *const T {
unsafe { intrinsics::ptr_offset_from(self, origin) }
}
/// Calculates the distance between two pointers. The returned value is in
/// Calculates the distance between two pointers within the same allocation. The returned value is in
/// units of **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
@ -695,7 +695,7 @@ pub fn mask(self, mask: usize) -> *const T {
unsafe { self.cast::<u8>().offset_from(origin.cast::<u8>()) }
}
/// Calculates the distance between two pointers, *where it's known that
/// Calculates the distance between two pointers within the same allocation, *where it's known that
/// `self` is equal to or greater than `origin`*. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
@ -790,6 +790,25 @@ const fn comptime(_: *const (), _: *const ()) -> bool {
unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
}
/// Calculates the distance between two pointers within the same allocation, *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<U: ?Sized>(self, origin: *const U) -> usize {
// SAFETY: the caller must uphold the safety contract for `sub_ptr`.
unsafe { self.cast::<u8>().sub_ptr(origin.cast::<u8>()) }
}
/// Returns whether two pointers are guaranteed to be equal.
///
/// At runtime this function behaves like `Some(self == other)`.

View File

@ -746,7 +746,7 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
(self as *const T).guaranteed_ne(other as _)
}
/// Calculates the distance between two pointers. The returned value is in
/// Calculates the distance between two pointers within the same allocation. The returned value is in
/// units of T: the distance in bytes divided by `mem::size_of::<T>()`.
///
/// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::<T>() as isize)`,
@ -839,7 +839,7 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
unsafe { (self as *const T).offset_from(origin) }
}
/// Calculates the distance between two pointers. The returned value is in
/// Calculates the distance between two pointers within the same allocation. The returned value is in
/// units of **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
@ -857,7 +857,7 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
unsafe { self.cast::<u8>().offset_from(origin.cast::<u8>()) }
}
/// Calculates the distance between two pointers, *where it's known that
/// Calculates the distance between two pointers within the same allocation, *where it's known that
/// `self` is equal to or greater than `origin`*. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
@ -930,6 +930,25 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
unsafe { (self as *const T).sub_ptr(origin) }
}
/// Calculates the distance between two pointers within the same allocation, *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<U: ?Sized>(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) }
}
/// Adds an unsigned offset to a pointer.
///
/// This can only move the pointer forward (or not move it). If you need to move forward or

View File

@ -676,7 +676,7 @@ pub const fn cast<U>(self) -> NonNull<U> {
unsafe { NonNull { pointer: self.pointer.byte_sub(count) } }
}
/// Calculates the distance between two pointers. The returned value is in
/// Calculates the distance between two pointers within the same allocation. The returned value is in
/// units of T: the distance in bytes divided by `mem::size_of::<T>()`.
///
/// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::<T>() as isize)`,
@ -773,7 +773,7 @@ pub const fn cast<U>(self) -> NonNull<U> {
unsafe { self.pointer.offset_from(origin.pointer) }
}
/// Calculates the distance between two pointers. The returned value is in
/// Calculates the distance between two pointers within the same allocation. The returned value is in
/// units of **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
@ -793,7 +793,7 @@ pub const fn cast<U>(self) -> NonNull<U> {
// N.B. `wrapping_offset``, `wrapping_add`, etc are not implemented because they can wrap to null
/// Calculates the distance between two pointers, *where it's known that
/// Calculates the distance between two pointers within the same allocation, *where it's known that
/// `self` is equal to or greater than `origin`*. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
@ -866,6 +866,25 @@ pub const fn cast<U>(self) -> NonNull<U> {
unsafe { self.pointer.sub_ptr(subtracted.pointer) }
}
/// Calculates the distance between two pointers within the same allocation, *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.
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: NonNull<U>) -> 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.
///