From 246f239d9f40f633160f0c18f87a20922d4e77bb Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:06:37 +0200 Subject: Merging debian version 1.65.0+dfsg1-2. Signed-off-by: Daniel Baumann --- library/core/src/ptr/const_ptr.rs | 107 ++++++++++++++++++++++---------------- library/core/src/ptr/metadata.rs | 18 ------- library/core/src/ptr/mod.rs | 18 ++++--- library/core/src/ptr/mut_ptr.rs | 98 ++++++++++++++++++---------------- 4 files changed, 126 insertions(+), 115 deletions(-) (limited to 'library/core/src/ptr') diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index e0655d68d..43e883b8b 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -36,7 +36,10 @@ impl *const T { pub const fn is_null(self) -> bool { // Compare via a cast to a thin pointer, so fat pointers are only // considering their "data" part for null-ness. - (self as *const u8).guaranteed_eq(null()) + match (self as *const u8).guaranteed_eq(null()) { + None => false, + Some(res) => res, + } } /// Casts to a pointer of another type. @@ -95,8 +98,8 @@ impl *const T { /// /// This is a bit safer than `as` because it wouldn't silently change the type if the code is /// refactored. - #[unstable(feature = "ptr_const_cast", issue = "92675")] - #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] pub const fn cast_mut(self) -> *mut T { self as _ } @@ -154,7 +157,7 @@ impl *const T { /// This is similar to `self as usize`, which semantically discards *provenance* and /// *address-space* information. However, unlike `self as usize`, casting the returned address /// back to a pointer yields [`invalid`][], which is undefined behavior to dereference. To - /// properly restore the lost information and obtain a dereferencable pointer, use + /// properly restore the lost information and obtain a dereferenceable pointer, use /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. /// /// If using those APIs is not possible because there is no way to preserve a pointer with the @@ -249,7 +252,7 @@ impl *const T { let offset = dest_addr.wrapping_sub(self_addr); // This is the canonical desugarring of this operation - self.cast::().wrapping_offset(offset).cast::() + self.wrapping_byte_offset(offset) } /// Creates a new pointer by mapping `self`'s address to a new one. @@ -559,6 +562,21 @@ impl *const T { from_raw_parts::(self.cast::().wrapping_offset(count).cast::<()>(), metadata(self)) } + /// Masks out bits of the pointer according to a mask. + /// + /// This is convenience for `ptr.map_addr(|a| a & mask)`. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[cfg(not(bootstrap))] + #[unstable(feature = "ptr_mask", issue = "98290")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + pub fn mask(self, mask: usize) -> *const T { + let this = intrinsics::ptr_mask(self.cast::<()>(), mask); + from_raw_parts::(this, metadata(self)) + } + /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::()`. /// @@ -641,7 +659,7 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_offset_from", since = "1.47.0")] - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")] + #[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset_from(self, origin: *const T) -> isize @@ -740,9 +758,12 @@ impl *const T { where T: Sized, { + let this = self; // SAFETY: The comparison has no side-effects, and the intrinsic // does this check internally in the CTFE implementation. - unsafe { assert_unsafe_precondition!(self >= origin) }; + unsafe { + assert_unsafe_precondition!([T](this: *const T, origin: *const T) => this >= origin) + }; let pointee_size = mem::size_of::(); assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); @@ -752,20 +773,16 @@ impl *const T { /// Returns whether two pointers are guaranteed to be equal. /// - /// At runtime this function behaves like `self == other`. + /// At runtime this function behaves like `Some(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. + /// spuriously return `None` for pointers that later actually turn out to have its equality known. + /// But when it returns `Some`, the pointers' equality is guaranteed to be known. /// - /// 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 must not + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must 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 + /// for performance optimizations where spurious `None` 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 @@ -774,29 +791,28 @@ impl *const T { #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] - pub const fn guaranteed_eq(self, other: *const T) -> bool + pub const fn guaranteed_eq(self, other: *const T) -> Option where T: Sized, { - intrinsics::ptr_guaranteed_eq(self, other) + match intrinsics::ptr_guaranteed_cmp(self as _, other as _) { + 2 => None, + other => Some(other == 1), + } } - /// Returns whether two pointers are guaranteed to be unequal. + /// Returns whether two pointers are guaranteed to be inequal. /// - /// At runtime this function behaves like `self != other`. + /// At runtime this function behaves like `Some(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 unequal. - /// But when it returns `true`, the pointers are guaranteed to be unequal. - /// - /// 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 + /// it is not always possible to determine inequality of two pointers, so this function may + /// spuriously return `None` for pointers that later actually turn out to have its inequality known. + /// But when it returns `Some`, the pointers' inequality is guaranteed to be known. /// - /// The return value may change depending on the compiler version and unsafe code must not + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must 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 + /// for performance optimizations where spurious `None` 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 @@ -805,11 +821,14 @@ impl *const T { #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] - pub const fn guaranteed_ne(self, other: *const T) -> bool + pub const fn guaranteed_ne(self, other: *const T) -> Option where T: Sized, { - intrinsics::ptr_guaranteed_ne(self, other) + match self.guaranteed_eq(other) { + None => None, + Some(eq) => Some(!eq), + } } /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`). @@ -1267,20 +1286,21 @@ impl *const T { /// Accessing adjacent `u8` as `u16` /// /// ``` - /// # fn foo(n: usize) { - /// # use std::mem::align_of; + /// use std::mem::align_of; + /// /// # unsafe { - /// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; - /// let ptr = x.as_ptr().add(n) as *const u8; + /// let x = [5_u8, 6, 7, 8, 9]; + /// let ptr = x.as_ptr(); /// let offset = ptr.align_offset(align_of::()); - /// if offset < x.len() - n - 1 { - /// let u16_ptr = ptr.add(offset) as *const u16; - /// assert_ne!(*u16_ptr, 500); + /// + /// if offset < x.len() - 1 { + /// let u16_ptr = ptr.add(offset).cast::(); + /// assert!(*u16_ptr == u16::from_ne_bytes([5, 6]) || *u16_ptr == u16::from_ne_bytes([6, 7])); /// } else { /// // while the pointer can be aligned via `offset`, it would point /// // outside the allocation /// } - /// # } } + /// # } /// ``` #[stable(feature = "align_offset", since = "1.36.0")] #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")] @@ -1336,11 +1356,8 @@ impl *const T { panic!("is_aligned_to: align is not a power-of-two"); } - // SAFETY: `is_power_of_two()` will return `false` for zero. - unsafe { core::intrinsics::assume(align != 0) }; - // Cast is needed for `T: !Sized` - self.cast::().addr() % align == 0 + self.cast::().addr() & align - 1 == 0 } } diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index cd5edee04..8865c834c 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -180,7 +180,6 @@ pub struct DynMetadata { phantom: crate::marker::PhantomData, } -#[cfg(not(bootstrap))] extern "C" { /// Opaque type for accessing vtables. /// @@ -189,17 +188,6 @@ extern "C" { type VTable; } -/// The common prefix of all vtables. It is followed by function pointers for trait methods. -/// -/// Private implementation detail of `DynMetadata::size_of` etc. -#[repr(C)] -#[cfg(bootstrap)] -struct VTable { - drop_in_place: fn(*mut ()), - size_of: usize, - align_of: usize, -} - impl DynMetadata { /// Returns the size of the type associated with this vtable. #[inline] @@ -207,9 +195,6 @@ impl DynMetadata { // Note that "size stored in vtable" is *not* the same as "result of size_of_val_raw". // Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the // `Send` part! - #[cfg(bootstrap)] - return self.vtable_ptr.size_of; - #[cfg(not(bootstrap))] // SAFETY: DynMetadata always contains a valid vtable pointer return unsafe { crate::intrinsics::vtable_size(self.vtable_ptr as *const VTable as *const ()) @@ -219,9 +204,6 @@ impl DynMetadata { /// Returns the alignment of the type associated with this vtable. #[inline] pub fn align_of(self) -> usize { - #[cfg(bootstrap)] - return self.vtable_ptr.align_of; - #[cfg(not(bootstrap))] // SAFETY: DynMetadata always contains a valid vtable pointer return unsafe { crate::intrinsics::vtable_align(self.vtable_ptr as *const VTable as *const ()) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 40e28e636..e976abed7 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -90,7 +90,7 @@ //! isn't *pointer*-sized but address-space/offset/allocation-sized (we'll probably continue //! to conflate these notions). This would potentially make it possible to more efficiently //! target platforms where pointers are larger than offsets, such as CHERI and maybe some -//! segmented architecures. +//! segmented architectures. //! //! ## Provenance //! @@ -172,7 +172,7 @@ //! a pointer to a usize is generally an operation which *only* extracts the address. It is //! therefore *impossible* to construct a valid pointer from a usize because there is no way //! to restore the address-space and provenance. In other words, pointer-integer-pointer -//! roundtrips are not possible (in the sense that the resulting pointer is not dereferencable). +//! roundtrips are not possible (in the sense that the resulting pointer is not dereferenceable). //! //! The key insight to making this model *at all* viable is the [`with_addr`][] method: //! @@ -272,7 +272,7 @@ //! //! * Create an invalid pointer from just an address (see [`ptr::invalid`][]). This can //! be used for sentinel values like `null` *or* to represent a tagged pointer that will -//! never be dereferencable. In general, it is always sound for an integer to pretend +//! never be dereferenceable. In general, it is always sound for an integer to pretend //! to be a pointer "for fun" as long as you don't use operations on it which require //! it to be valid (offset, read, write, etc). //! @@ -603,6 +603,7 @@ pub const fn invalid_mut(addr: usize) -> *mut T { #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn from_exposed_addr(addr: usize) -> *const T where T: Sized, @@ -639,6 +640,7 @@ where #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn from_exposed_addr_mut(addr: usize) -> *mut T where T: Sized, @@ -884,7 +886,7 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { // SAFETY: the caller must guarantee that `x` and `y` are // valid for writes and properly aligned. unsafe { - assert_unsafe_precondition!( + assert_unsafe_precondition!([T](x: *mut T, y: *mut T, count: usize) => is_aligned_and_not_null(x) && is_aligned_and_not_null(y) && is_nonoverlapping(x, y, count) @@ -981,7 +983,7 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { // and cannot overlap `src` since `dst` must point to a distinct // allocated object. unsafe { - assert_unsafe_precondition!(is_aligned_and_not_null(dst)); + assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst)); mem::swap(&mut *dst, &mut src); // cannot overlap } src @@ -1468,7 +1470,7 @@ pub const unsafe fn write_unaligned(dst: *mut T, src: T) { pub unsafe fn read_volatile(src: *const T) -> T { // SAFETY: the caller must uphold the safety contract for `volatile_load`. unsafe { - assert_unsafe_precondition!(is_aligned_and_not_null(src)); + assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src)); intrinsics::volatile_load(src) } } @@ -1539,7 +1541,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { pub unsafe fn write_volatile(dst: *mut T, src: T) { // SAFETY: the caller must uphold the safety contract for `volatile_store`. unsafe { - assert_unsafe_precondition!(is_aligned_and_not_null(dst)); + assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst)); intrinsics::volatile_store(dst, src); } } @@ -1834,7 +1836,7 @@ macro_rules! maybe_fnptr_doc { $item }; ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(fake_variadic))] + #[doc(fake_variadic)] #[doc = "This trait is implemented for function pointers with up to twelve arguments."] #[$meta] $item diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index fc3dd2a9b..e277b8181 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -35,7 +35,10 @@ impl *mut T { pub const fn is_null(self) -> bool { // Compare via a cast to a thin pointer, so fat pointers are only // considering their "data" part for null-ness. - (self as *mut u8).guaranteed_eq(null_mut()) + match (self as *mut u8).guaranteed_eq(null_mut()) { + None => false, + Some(res) => res, + } } /// Casts to a pointer of another type. @@ -100,8 +103,8 @@ impl *mut T { /// coercion. /// /// [`cast_mut`]: #method.cast_mut - #[unstable(feature = "ptr_const_cast", issue = "92675")] - #[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")] + #[stable(feature = "ptr_const_cast", since = "1.65.0")] + #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] pub const fn cast_const(self) -> *const T { self as _ } @@ -160,7 +163,7 @@ impl *mut T { /// This is similar to `self as usize`, which semantically discards *provenance* and /// *address-space* information. However, unlike `self as usize`, casting the returned address /// back to a pointer yields [`invalid`][], which is undefined behavior to dereference. To - /// properly restore the lost information and obtain a dereferencable pointer, use + /// properly restore the lost information and obtain a dereferenceable pointer, use /// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr]. /// /// If using those APIs is not possible because there is no way to preserve a pointer with the @@ -255,7 +258,7 @@ impl *mut T { let offset = dest_addr.wrapping_sub(self_addr); // This is the canonical desugarring of this operation - self.cast::().wrapping_offset(offset).cast::() + self.wrapping_byte_offset(offset) } /// Creates a new pointer by mapping `self`'s address to a new one. @@ -575,6 +578,21 @@ impl *mut T { ) } + /// Masks out bits of the pointer according to a mask. + /// + /// This is convenience for `ptr.map_addr(|a| a & mask)`. + /// + /// For non-`Sized` pointees this operation changes only the data pointer, + /// leaving the metadata untouched. + #[cfg(not(bootstrap))] + #[unstable(feature = "ptr_mask", issue = "98290")] + #[must_use = "returns a new pointer rather than modifying its argument"] + #[inline(always)] + pub fn mask(self, mask: usize) -> *mut T { + let this = intrinsics::ptr_mask(self.cast::<()>(), mask) as *mut (); + from_raw_parts_mut::(this, metadata(self)) + } + /// Returns `None` if the pointer is null, or else returns a unique reference to /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`] /// must be used instead. @@ -682,20 +700,16 @@ impl *mut T { /// Returns whether two pointers are guaranteed to be equal. /// - /// At runtime this function behaves like `self == other`. + /// At runtime this function behaves like `Some(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. + /// spuriously return `None` for pointers that later actually turn out to have its equality known. + /// But when it returns `Some`, the pointers' equality is guaranteed to be known. /// - /// 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 might not + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must 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 + /// for performance optimizations where spurious `None` 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 @@ -704,29 +718,25 @@ impl *mut T { #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] - pub const fn guaranteed_eq(self, other: *mut T) -> bool + pub const fn guaranteed_eq(self, other: *mut T) -> Option where T: Sized, { - intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _) + (self as *const T).guaranteed_eq(other as _) } - /// Returns whether two pointers are guaranteed to be unequal. + /// Returns whether two pointers are guaranteed to be inequal. /// - /// At runtime this function behaves like `self != other`. + /// At runtime this function behaves like `Some(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 unequal. - /// But when it returns `true`, the pointers are guaranteed to be unequal. - /// - /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer - /// comparisons for which both functions return `false`. + /// it is not always possible to determine inequality of two pointers, so this function may + /// spuriously return `None` for pointers that later actually turn out to have its inequality known. + /// But when it returns `Some`, the pointers' inequality is guaranteed to be known. /// - /// [`guaranteed_eq`]: #method.guaranteed_eq - /// - /// The return value may change depending on the compiler version and unsafe code might not + /// The return value may change from `Some` to `None` and vice versa depending on the compiler + /// version and unsafe code must 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 + /// for performance optimizations where spurious `None` 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 @@ -735,11 +745,11 @@ impl *mut T { #[unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")] #[inline] - pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool + pub const fn guaranteed_ne(self, other: *mut T) -> Option where T: Sized, { - intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _) + (self as *const T).guaranteed_ne(other as _) } /// Calculates the distance between two pointers. The returned value is in @@ -824,7 +834,7 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_offset_from", since = "1.47.0")] - #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "92980")] + #[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset_from(self, origin: *const T) -> isize @@ -1545,20 +1555,23 @@ impl *mut T { /// Accessing adjacent `u8` as `u16` /// /// ``` - /// # fn foo(n: usize) { - /// # use std::mem::align_of; + /// use std::mem::align_of; + /// /// # unsafe { - /// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; - /// let ptr = x.as_ptr().add(n) as *const u8; + /// let mut x = [5_u8, 6, 7, 8, 9]; + /// let ptr = x.as_mut_ptr(); /// let offset = ptr.align_offset(align_of::()); - /// if offset < x.len() - n - 1 { - /// let u16_ptr = ptr.add(offset) as *const u16; - /// assert_ne!(*u16_ptr, 500); + /// + /// if offset < x.len() - 1 { + /// let u16_ptr = ptr.add(offset).cast::(); + /// *u16_ptr = 0; + /// + /// assert!(x == [0, 0, 7, 8, 9] || x == [5, 0, 0, 8, 9]); /// } else { /// // while the pointer can be aligned via `offset`, it would point /// // outside the allocation /// } - /// # } } + /// # } /// ``` #[stable(feature = "align_offset", since = "1.36.0")] #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")] @@ -1614,11 +1627,8 @@ impl *mut T { panic!("is_aligned_to: align is not a power-of-two"); } - // SAFETY: `is_power_of_two()` will return `false` for zero. - unsafe { core::intrinsics::assume(align != 0) }; - // Cast is needed for `T: !Sized` - self.cast::().addr() % align == 0 + self.cast::().addr() & align - 1 == 0 } } -- cgit v1.2.3