1#![unstable(feature = "ptr_metadata", issue = "81513")]
2
3use crate::fmt;
4use crate::hash::{Hash, Hasher};
5#[cfg(not(bootstrap))]
6use crate::intrinsics::aggregate_raw_ptr;
7use crate::marker::Freeze;
8
9/// Provides the pointer metadata type of any pointed-to type.
10///
11/// # Pointer metadata
12///
13/// Raw pointer types and reference types in Rust can be thought of as made of two parts:
14/// a data pointer that contains the memory address of the value, and some metadata.
15///
16/// For statically-sized types (that implement the `Sized` traits)
17/// as well as for `extern` types,
18/// pointers are said to be “thin”: metadata is zero-sized and its type is `()`.
19///
20/// Pointers to [dynamically-sized types][dst] are said to be “wide” or “fat”,
21/// they have non-zero-sized metadata:
22///
23/// * For structs whose last field is a DST, metadata is the metadata for the last field
24/// * For the `str` type, metadata is the length in bytes as `usize`
25/// * For slice types like `[T]`, metadata is the length in items as `usize`
26/// * For trait objects like `dyn SomeTrait`, metadata is [`DynMetadata<Self>`][DynMetadata]
27/// (e.g. `DynMetadata<dyn SomeTrait>`)
28///
29/// In the future, the Rust language may gain new kinds of types
30/// that have different pointer metadata.
31///
32/// [dst]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts
33///
34///
35/// # The `Pointee` trait
36///
37/// The point of this trait is its `Metadata` associated type,
38/// which is `()` or `usize` or `DynMetadata<_>` as described above.
39/// It is automatically implemented for every type.
40/// It can be assumed to be implemented in a generic context, even without a corresponding bound.
41///
42///
43/// # Usage
44///
45/// Raw pointers can be decomposed into the data pointer and metadata components
46/// with their [`to_raw_parts`] method.
47///
48/// Alternatively, metadata alone can be extracted with the [`metadata`] function.
49/// A reference can be passed to [`metadata`] and implicitly coerced.
50///
51/// A (possibly-wide) pointer can be put back together from its data pointer and metadata
52/// with [`from_raw_parts`] or [`from_raw_parts_mut`].
53///
54/// [`to_raw_parts`]: *const::to_raw_parts
55#[lang = "pointee_trait"]
56#[rustc_deny_explicit_impl(implement_via_object = false)]
57pub trait Pointee {
58 /// The type for metadata in pointers and references to `Self`.
59 #[lang = "metadata_type"]
60 // NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata`
61 // in `library/core/src/ptr/metadata.rs`
62 // in sync with those here:
63 type Metadata: fmt::Debug + Copy + Send + Sync + Ord + Hash + Unpin + Freeze;
64}
65
66/// Pointers to types implementing this trait alias are “thin”.
67///
68/// This includes statically-`Sized` types and `extern` types.
69///
70/// # Example
71///
72/// ```rust
73/// #![feature(ptr_metadata)]
74///
75/// fn this_never_panics<T: std::ptr::Thin>() {
76/// assert_eq!(std::mem::size_of::<&T>(), std::mem::size_of::<usize>())
77/// }
78/// ```
79#[unstable(feature = "ptr_metadata", issue = "81513")]
80// NOTE: don’t stabilize this before trait aliases are stable in the language?
81pub trait Thin = Pointee<Metadata = ()>;
82
83/// Extract the metadata component of a pointer.
84///
85/// Values of type `*mut T`, `&T`, or `&mut T` can be passed directly to this function
86/// as they implicitly coerce to `*const T`.
87///
88/// # Example
89///
90/// ```
91/// #![feature(ptr_metadata)]
92///
93/// assert_eq!(std::ptr::metadata("foo"), 3_usize);
94/// ```
95#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
96#[inline]
97pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
98 // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
99 // and PtrComponents<T> have the same memory layouts. Only std can make this
100 // guarantee.
101 unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
102}
103
104/// Forms a (possibly-wide) raw pointer from a data pointer and metadata.
105///
106/// This function is safe but the returned pointer is not necessarily safe to dereference.
107/// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements.
108/// For trait objects, the metadata must come from a pointer to the same underlying erased type.
109///
110/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
111#[unstable(feature = "ptr_metadata", issue = "81513")]
112#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
113#[inline]
114pub const fn from_raw_parts<T: ?Sized>(
115 data_pointer: *const (),
116 metadata: <T as Pointee>::Metadata,
117) -> *const T {
118 #[cfg(bootstrap)]
119 {
120 // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
121 // and PtrComponents<T> have the same memory layouts. Only std can make this
122 // guarantee.
123 unsafe { PtrRepr { components: PtrComponents { data_pointer, metadata } }.const_ptr }
124 }
125 #[cfg(not(bootstrap))]
126 {
127 aggregate_raw_ptr(data_pointer, _meta:metadata)
128 }
129}
130
131/// Performs the same functionality as [`from_raw_parts`], except that a
132/// raw `*mut` pointer is returned, as opposed to a raw `*const` pointer.
133///
134/// See the documentation of [`from_raw_parts`] for more details.
135#[unstable(feature = "ptr_metadata", issue = "81513")]
136#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
137#[inline]
138pub const fn from_raw_parts_mut<T: ?Sized>(
139 data_pointer: *mut (),
140 metadata: <T as Pointee>::Metadata,
141) -> *mut T {
142 #[cfg(bootstrap)]
143 {
144 // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
145 // and PtrComponents<T> have the same memory layouts. Only std can make this
146 // guarantee.
147 unsafe { PtrRepr { components: PtrComponents { data_pointer, metadata } }.mut_ptr }
148 }
149 #[cfg(not(bootstrap))]
150 {
151 aggregate_raw_ptr(data_pointer, _meta:metadata)
152 }
153}
154
155#[repr(C)]
156union PtrRepr<T: ?Sized> {
157 const_ptr: *const T,
158 mut_ptr: *mut T,
159 components: PtrComponents<T>,
160}
161
162#[repr(C)]
163struct PtrComponents<T: ?Sized> {
164 data_pointer: *const (),
165 metadata: <T as Pointee>::Metadata,
166}
167
168// Manual impl needed to avoid `T: Copy` bound.
169impl<T: ?Sized> Copy for PtrComponents<T> {}
170
171// Manual impl needed to avoid `T: Clone` bound.
172impl<T: ?Sized> Clone for PtrComponents<T> {
173 fn clone(&self) -> Self {
174 *self
175 }
176}
177
178/// The metadata for a `Dyn = dyn SomeTrait` trait object type.
179///
180/// It is a pointer to a vtable (virtual call table)
181/// that represents all the necessary information
182/// to manipulate the concrete type stored inside a trait object.
183/// The vtable notably contains:
184///
185/// * type size
186/// * type alignment
187/// * a pointer to the type’s `drop_in_place` impl (may be a no-op for plain-old-data)
188/// * pointers to all the methods for the type’s implementation of the trait
189///
190/// Note that the first three are special because they’re necessary to allocate, drop,
191/// and deallocate any trait object.
192///
193/// It is possible to name this struct with a type parameter that is not a `dyn` trait object
194/// (for example `DynMetadata<u64>`) but not to obtain a meaningful value of that struct.
195///
196/// Note that while this type implements `PartialEq`, comparing vtable pointers is unreliable:
197/// pointers to vtables of the same type for the same trait can compare inequal (because vtables are
198/// duplicated in multiple codegen units), and pointers to vtables of *different* types/traits can
199/// compare equal (since identical vtables can be deduplicated within a codegen unit).
200#[lang = "dyn_metadata"]
201pub struct DynMetadata<Dyn: ?Sized> {
202 vtable_ptr: &'static VTable,
203 phantom: crate::marker::PhantomData<Dyn>,
204}
205
206extern "C" {
207 /// Opaque type for accessing vtables.
208 ///
209 /// Private implementation detail of `DynMetadata::size_of` etc.
210 /// There is conceptually not actually any Abstract Machine memory behind this pointer.
211 type VTable;
212}
213
214impl<Dyn: ?Sized> DynMetadata<Dyn> {
215 /// Returns the size of the type associated with this vtable.
216 #[inline]
217 pub fn size_of(self) -> usize {
218 // Note that "size stored in vtable" is *not* the same as "result of size_of_val_raw".
219 // Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the
220 // `Send` part!
221 // SAFETY: DynMetadata always contains a valid vtable pointer
222 return unsafe {
223 crate::intrinsics::vtable_size(self.vtable_ptr as *const VTable as *const ())
224 };
225 }
226
227 /// Returns the alignment of the type associated with this vtable.
228 #[inline]
229 pub fn align_of(self) -> usize {
230 // SAFETY: DynMetadata always contains a valid vtable pointer
231 return unsafe {
232 crate::intrinsics::vtable_align(self.vtable_ptr as *const VTable as *const ())
233 };
234 }
235
236 /// Returns the size and alignment together as a `Layout`
237 #[inline]
238 pub fn layout(self) -> crate::alloc::Layout {
239 // SAFETY: the compiler emitted this vtable for a concrete Rust type which
240 // is known to have a valid layout. Same rationale as in `Layout::for_value`.
241 unsafe { crate::alloc::Layout::from_size_align_unchecked(self.size_of(), self.align_of()) }
242 }
243}
244
245unsafe impl<Dyn: ?Sized> Send for DynMetadata<Dyn> {}
246unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}
247
248impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 f.debug_tuple(name:"DynMetadata").field(&(self.vtable_ptr as *const VTable)).finish()
251 }
252}
253
254// Manual impls needed to avoid `Dyn: $Trait` bounds.
255
256impl<Dyn: ?Sized> Unpin for DynMetadata<Dyn> {}
257
258impl<Dyn: ?Sized> Copy for DynMetadata<Dyn> {}
259
260impl<Dyn: ?Sized> Clone for DynMetadata<Dyn> {
261 #[inline]
262 fn clone(&self) -> Self {
263 *self
264 }
265}
266
267impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}
268
269impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> {
270 #[inline]
271 fn eq(&self, other: &Self) -> bool {
272 crate::ptr::eq::<VTable>(self.vtable_ptr, b:other.vtable_ptr)
273 }
274}
275
276impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
277 #[inline]
278 #[allow(ambiguous_wide_pointer_comparisons)]
279 fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
280 (self.vtable_ptr as *const VTable).cmp(&(other.vtable_ptr as *const VTable))
281 }
282}
283
284impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
285 #[inline]
286 fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
287 Some(self.cmp(other))
288 }
289}
290
291impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
292 #[inline]
293 fn hash<H: Hasher>(&self, hasher: &mut H) {
294 crate::ptr::hash::<VTable, _>(self.vtable_ptr, into:hasher)
295 }
296}
297