@@ -92,10 +92,14 @@ pub trait Thin = Pointee<Metadata = ()>;
9292 #[ rustc_const_unstable( feature = "ptr_metadata", issue = "81513 ") ]
9393#[ inline]
9494pub const fn metadata < T : ?Sized > ( ptr: * const T ) -> <T as Pointee >:: Metadata {
95- // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
96- // and PtrComponents<T> have the same memory layouts. Only std can make this
97- // guarantee.
98- unsafe { PtrRepr { const_ptr: ptr } . components. metadata }
95+ metadata_flexible( ptr)
96+ }
97+
98+ #[ inline]
99+ const fn metadata_flexible < P : RawPointer > ( ptr : P ) -> <P :: Pointee as Pointee >:: Metadata {
100+ // SAFETY: Transmuting like this is safe since `P` and `PtrComponents<P, _>`
101+ // have the same memory layouts. Only std can make this guarantee.
102+ unsafe { crate :: intrinsics:: transmute_unchecked :: < P , PtrComponents < P :: Pointee > > ( ptr) . metadata }
99103}
100104
101105/// Forms a (possibly-wide) raw pointer from a data pointer and metadata.
@@ -112,10 +116,7 @@ pub const fn from_raw_parts<T: ?Sized>(
112116 data_pointer : * const ( ) ,
113117 metadata : <T as Pointee >:: Metadata ,
114118) -> * const T {
115- // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
116- // and PtrComponents<T> have the same memory layouts. Only std can make this
117- // guarantee.
118- unsafe { PtrRepr { components : PtrComponents { data_pointer, metadata } } . const_ptr }
119+ from_raw_parts_flexible ( data_pointer, metadata)
119120}
120121
121122/// Performs the same functionality as [`from_raw_parts`], except that a
@@ -129,30 +130,64 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
129130 data_pointer : * mut ( ) ,
130131 metadata : <T as Pointee >:: Metadata ,
131132) -> * mut T {
132- // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
133- // and PtrComponents<T> have the same memory layouts. Only std can make this
134- // guarantee.
135- unsafe { PtrRepr { components : PtrComponents { data_pointer, metadata } } . mut_ptr }
133+ from_raw_parts_flexible ( data_pointer, metadata)
136134}
137135
138- #[ repr( C ) ]
139- union PtrRepr < T : ?Sized > {
140- const_ptr : * const T ,
141- mut_ptr : * mut T ,
142- components : PtrComponents < T > ,
136+ /// Just like [`from_raw_parts`] and [`from_raw_parts_mut`], but more flexible
137+ /// in terms of which types it can take, allowing smaller MIR.
138+ // See <https://github.com/rust-lang/rust/issues/123174>
139+ #[ rustc_const_unstable( feature = "ptr_metadata" , issue = "81513" ) ]
140+ #[ inline]
141+ pub ( crate ) const fn from_raw_parts_flexible < P : RawPointer > (
142+ data_pointer : impl RawPointer < Pointee : Thin > ,
143+ metadata : <P :: Pointee as Pointee >:: Metadata ,
144+ ) -> P {
145+ // SAFETY: Transmuting like this is safe since `P` and `PtrComponents<P, _>`
146+ // have the same memory layouts. Only std can make this guarantee.
147+ unsafe {
148+ crate :: intrinsics:: transmute_unchecked :: < PtrComponents < P :: Pointee , _ > , P > ( PtrComponents {
149+ data_pointer,
150+ metadata,
151+ } )
152+ }
153+ }
154+
155+ use private_bounds:: RawPointer ;
156+ mod private_bounds {
157+ /// Internal trait to avoid bad instantiations of [`PtrComponents`]
158+ ///
159+ /// # Safety
160+ ///
161+ /// Must have the same layout as `*const Self::Pointee` and be able to hold provenance.
162+ pub unsafe trait RawPointer {
163+ type Pointee : ?Sized + super :: Pointee ;
164+ }
165+ }
166+
167+ // SAFETY: `*const T` is obviously a raw pointer
168+ unsafe impl < T : ?Sized > RawPointer for * const T {
169+ type Pointee = T ;
170+ }
171+ // SAFETY: `*mut T` is obviously a raw pointer
172+ unsafe impl < T : ?Sized > RawPointer for * mut T {
173+ type Pointee = T ;
174+ }
175+ // SAFETY: `NonNull<T>` is a transparent newtype around a `*const T`.
176+ unsafe impl < T : ?Sized > RawPointer for super :: NonNull < T > {
177+ type Pointee = T ;
143178}
144179
145180#[ repr( C ) ]
146- struct PtrComponents < T : ?Sized > {
147- data_pointer : * const ( ) ,
181+ struct PtrComponents < T : ?Sized , P = * const ( ) > {
182+ data_pointer : P ,
148183 metadata : <T as Pointee >:: Metadata ,
149184}
150185
151186// Manual impl needed to avoid `T: Copy` bound.
152- impl < T : ?Sized > Copy for PtrComponents < T > { }
187+ impl < T : ?Sized , P : Copy > Copy for PtrComponents < T , P > { }
153188
154189// Manual impl needed to avoid `T: Clone` bound.
155- impl < T : ?Sized > Clone for PtrComponents < T > {
190+ impl < T : ?Sized , P : Copy > Clone for PtrComponents < T , P > {
156191 fn clone ( & self ) -> Self {
157192 * self
158193 }
0 commit comments