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