From 6c54745784b03e614a7a152ef010c05207156c2a Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 28 Oct 2022 23:05:22 +0400 Subject: [PATCH 1/2] Make `pointer::with_metadata_of` const (+simplify implementation) --- library/core/src/ptr/const_ptr.rs | 11 +++-------- library/core/src/ptr/mut_ptr.rs | 15 +++------------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index ed16c5f051f7b..56246ccfa8ae9 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -79,19 +79,14 @@ impl *const T { /// } /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] + #[rustc_const_unstable(feature = "set_ptr_value", issue = "75091")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] - pub fn with_metadata_of(self, mut val: *const U) -> *const U + pub const fn with_metadata_of(self, meta: *const U) -> *const U where U: ?Sized, { - let target = &mut val as *mut *const U as *mut *const u8; - // SAFETY: In case of a thin pointer, this operations is identical - // to a simple assignment. In case of a fat pointer, with the current - // fat pointer layout implementation, the first field of such a - // pointer is always the data pointer, which is likewise assigned. - unsafe { *target = self as *const u8 }; - val + from_raw_parts::(self as *const (), metadata(meta)) } /// Changes constness without changing the type. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6764002bcd434..ddbe69d97f260 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -78,23 +78,14 @@ impl *mut T { /// } /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] + #[rustc_const_unstable(feature = "set_ptr_value", issue = "75091")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] - pub fn with_metadata_of(self, val: *const U) -> *mut U + pub const fn with_metadata_of(self, meta: *const U) -> *mut U where U: ?Sized, { - // Prepare in the type system that we will replace the pointer value with a mutable - // pointer, taking the mutable provenance from the `self` pointer. - let mut val = val as *mut U; - // Pointer to the pointer value within the value. - let target = &mut val as *mut *mut U as *mut *mut u8; - // SAFETY: In case of a thin pointer, this operations is identical - // to a simple assignment. In case of a fat pointer, with the current - // fat pointer layout implementation, the first field of such a - // pointer is always the data pointer, which is likewise assigned. - unsafe { *target = self as *mut u8 }; - val + from_raw_parts_mut::(self as *mut (), metadata(meta)) } /// Changes constness without changing the type. From d3b51926f81cd15740d5a06172a2697bee1d6dfc Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 28 Oct 2022 23:06:29 +0400 Subject: [PATCH 2/2] Simplify implementation of various pointer methods --- library/core/src/lib.rs | 1 + library/core/src/ptr/const_ptr.rs | 18 +++++++----------- library/core/src/ptr/mut_ptr.rs | 21 +++++++-------------- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 659409557c910..a68d8b55e3094 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -154,6 +154,7 @@ #![feature(maybe_uninit_uninit_array)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] +#![feature(set_ptr_value)] #![feature(slice_ptr_get)] #![feature(slice_split_at_unchecked)] #![feature(str_internals)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 56246ccfa8ae9..85e2b425c4046 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -473,8 +473,7 @@ impl *const T { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset(self, count: isize) -> Self { // SAFETY: the caller must uphold the safety contract for `offset`. - let this = unsafe { self.cast::().offset(count).cast::<()>() }; - from_raw_parts::(this, metadata(self)) + unsafe { self.cast::().offset(count).with_metadata_of(self) } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -554,7 +553,7 @@ impl *const T { #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] pub const fn wrapping_byte_offset(self, count: isize) -> Self { - from_raw_parts::(self.cast::().wrapping_offset(count).cast::<()>(), metadata(self)) + self.cast::().wrapping_offset(count).with_metadata_of(self) } /// Masks out bits of the pointer according to a mask. @@ -567,8 +566,7 @@ impl *const T { #[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)) + intrinsics::ptr_mask(self.cast::<()>(), mask).with_metadata_of(self) } /// Calculates the distance between two pointers. The returned value is in @@ -906,8 +904,7 @@ impl *const T { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_add(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `add`. - let this = unsafe { self.cast::().add(count).cast::<()>() }; - from_raw_parts::(this, metadata(self)) + unsafe { self.cast::().add(count).with_metadata_of(self) } } /// Calculates the offset from a pointer (convenience for @@ -993,8 +990,7 @@ impl *const T { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `sub`. - let this = unsafe { self.cast::().sub(count).cast::<()>() }; - from_raw_parts::(this, metadata(self)) + unsafe { self.cast::().sub(count).with_metadata_of(self) } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -1074,7 +1070,7 @@ impl *const T { #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] pub const fn wrapping_byte_add(self, count: usize) -> Self { - from_raw_parts::(self.cast::().wrapping_add(count).cast::<()>(), metadata(self)) + self.cast::().wrapping_add(count).with_metadata_of(self) } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -1154,7 +1150,7 @@ impl *const T { #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] pub const fn wrapping_byte_sub(self, count: usize) -> Self { - from_raw_parts::(self.cast::().wrapping_sub(count).cast::<()>(), metadata(self)) + self.cast::().wrapping_sub(count).with_metadata_of(self) } /// Reads the value from `self` without moving it. This leaves the diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index ddbe69d97f260..cff41e3654280 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -487,8 +487,7 @@ impl *mut T { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset(self, count: isize) -> Self { // SAFETY: the caller must uphold the safety contract for `offset`. - let this = unsafe { self.cast::().offset(count).cast::<()>() }; - from_raw_parts_mut::(this, metadata(self)) + unsafe { self.cast::().offset(count).with_metadata_of(self) } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -567,10 +566,7 @@ impl *mut T { #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] pub const fn wrapping_byte_offset(self, count: isize) -> Self { - from_raw_parts_mut::( - self.cast::().wrapping_offset(count).cast::<()>(), - metadata(self), - ) + self.cast::().wrapping_offset(count).with_metadata_of(self) } /// Masks out bits of the pointer according to a mask. @@ -583,8 +579,7 @@ impl *mut T { #[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)) + intrinsics::ptr_mask(self.cast::<()>(), mask).cast_mut().with_metadata_of(self) } /// Returns `None` if the pointer is null, or else returns a unique reference to @@ -1011,8 +1006,7 @@ impl *mut T { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_add(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `add`. - let this = unsafe { self.cast::().add(count).cast::<()>() }; - from_raw_parts_mut::(this, metadata(self)) + unsafe { self.cast::().add(count).with_metadata_of(self) } } /// Calculates the offset from a pointer (convenience for @@ -1098,8 +1092,7 @@ impl *mut T { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub(self, count: usize) -> Self { // SAFETY: the caller must uphold the safety contract for `sub`. - let this = unsafe { self.cast::().sub(count).cast::<()>() }; - from_raw_parts_mut::(this, metadata(self)) + unsafe { self.cast::().sub(count).with_metadata_of(self) } } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -1179,7 +1172,7 @@ impl *mut T { #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] pub const fn wrapping_byte_add(self, count: usize) -> Self { - from_raw_parts_mut::(self.cast::().wrapping_add(count).cast::<()>(), metadata(self)) + self.cast::().wrapping_add(count).with_metadata_of(self) } /// Calculates the offset from a pointer using wrapping arithmetic. @@ -1259,7 +1252,7 @@ impl *mut T { #[unstable(feature = "pointer_byte_offsets", issue = "96283")] #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")] pub const fn wrapping_byte_sub(self, count: usize) -> Self { - from_raw_parts_mut::(self.cast::().wrapping_sub(count).cast::<()>(), metadata(self)) + self.cast::().wrapping_sub(count).with_metadata_of(self) } /// Reads the value from `self` without moving it. This leaves the