1 #![unstable(feature = "ptr_metadata", issue = "81513")]
4 use crate::hash
::{Hash, Hasher}
;
6 /// Provides the pointer metadata type of any pointed-to type.
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.
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 `()`.
17 /// Pointers to [dynamically-sized types][dst] are said to be “wide” or “fat”,
18 /// they have non-zero-sized metadata:
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>`)
26 /// In the future, the Rust language may gain new kinds of types
27 /// that have different pointer metadata.
29 /// [dst]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts
32 /// # The `Pointee` trait
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.
42 /// Raw pointers can be decomposed into the data address and metadata components
43 /// with their [`to_raw_parts`] method.
45 /// Alternatively, metadata alone can be extracted with the [`metadata`] function.
46 /// A reference can be passed to [`metadata`] and implicitly coerced.
48 /// A (possibly-wide) pointer can be put back together from its address and metadata
49 /// with [`from_raw_parts`] or [`from_raw_parts_mut`].
51 /// [`to_raw_parts`]: *const::to_raw_parts
52 #[lang = "pointee_trait"]
53 #[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
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
;
63 /// Pointers to types implementing this trait alias are “thin”.
65 /// This includes statically-`Sized` types and `extern` types.
70 /// #![feature(ptr_metadata)]
72 /// fn this_never_panics<T: std::ptr::Thin>() {
73 /// assert_eq!(std::mem::size_of::<&T>(), std::mem::size_of::<usize>())
76 #[unstable(feature = "ptr_metadata", issue = "81513")]
77 // NOTE: don’t stabilize this before trait aliases are stable in the language?
78 pub trait Thin
= Pointee
<Metadata
= ()>;
80 /// Extract the metadata component of a pointer.
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`.
88 /// #![feature(ptr_metadata)]
90 /// assert_eq!(std::ptr::metadata("foo"), 3_usize);
92 #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
94 pub 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
98 unsafe { PtrRepr { const_ptr: ptr }
.components
.metadata
}
101 /// Forms a (possibly-wide) raw pointer from a data address and metadata.
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.
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")]
111 pub const fn from_raw_parts
<T
: ?Sized
>(
112 data_address
: *const (),
113 metadata
: <T
as Pointee
>::Metadata
,
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
118 unsafe { PtrRepr { components: PtrComponents { data_address, metadata }
}.const_ptr
}
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.
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")]
128 pub const fn from_raw_parts_mut
<T
: ?Sized
>(
129 data_address
: *mut (),
130 metadata
: <T
as Pointee
>::Metadata
,
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
135 unsafe { PtrRepr { components: PtrComponents { data_address, metadata }
}.mut_ptr
}
139 union PtrRepr
<T
: ?Sized
> {
142 components
: PtrComponents
<T
>,
146 struct PtrComponents
<T
: ?Sized
> {
147 data_address
: *const (),
148 metadata
: <T
as Pointee
>::Metadata
,
151 // Manual impl needed to avoid `T: Copy` bound.
152 impl<T
: ?Sized
> Copy
for PtrComponents
<T
> {}
154 // Manual impl needed to avoid `T: Clone` bound.
155 impl<T
: ?Sized
> Clone
for PtrComponents
<T
> {
156 fn clone(&self) -> Self {
161 /// The metadata for a `Dyn = dyn SomeTrait` trait object type.
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:
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
173 /// Note that the first three are special because they’re necessary to allocate, drop,
174 /// and deallocate any trait object.
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"]
179 pub struct DynMetadata
<Dyn
: ?Sized
> {
180 vtable_ptr
: &'
static VTable
,
181 phantom
: crate::marker
::PhantomData
<Dyn
>,
185 /// Opaque type for accessing vtables.
187 /// Private implementation detail of `DynMetadata::size_of` etc.
188 /// There is conceptually not actually any Abstract Machine memory behind this pointer.
192 impl<Dyn
: ?Sized
> DynMetadata
<Dyn
> {
193 /// Returns the size of the type associated with this vtable.
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
199 // SAFETY: DynMetadata always contains a valid vtable pointer
201 crate::intrinsics
::vtable_size(self.vtable_ptr
as *const VTable
as *const ())
205 /// Returns the alignment of the type associated with this vtable.
207 pub fn align_of(self) -> usize {
208 // SAFETY: DynMetadata always contains a valid vtable pointer
210 crate::intrinsics
::vtable_align(self.vtable_ptr
as *const VTable
as *const ())
214 /// Returns the size and alignment together as a `Layout`
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()) }
223 unsafe impl<Dyn
: ?Sized
> Send
for DynMetadata
<Dyn
> {}
224 unsafe impl<Dyn
: ?Sized
> Sync
for DynMetadata
<Dyn
> {}
226 impl<Dyn
: ?Sized
> fmt
::Debug
for DynMetadata
<Dyn
> {
227 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
228 f
.debug_tuple("DynMetadata").field(&(self.vtable_ptr
as *const VTable
)).finish()
232 // Manual impls needed to avoid `Dyn: $Trait` bounds.
234 impl<Dyn
: ?Sized
> Unpin
for DynMetadata
<Dyn
> {}
236 impl<Dyn
: ?Sized
> Copy
for DynMetadata
<Dyn
> {}
238 impl<Dyn
: ?Sized
> Clone
for DynMetadata
<Dyn
> {
240 fn clone(&self) -> Self {
245 impl<Dyn
: ?Sized
> Eq
for DynMetadata
<Dyn
> {}
247 impl<Dyn
: ?Sized
> PartialEq
for DynMetadata
<Dyn
> {
249 fn eq(&self, other
: &Self) -> bool
{
250 crate::ptr
::eq
::<VTable
>(self.vtable_ptr
, other
.vtable_ptr
)
254 impl<Dyn
: ?Sized
> Ord
for DynMetadata
<Dyn
> {
256 fn cmp(&self, other
: &Self) -> crate::cmp
::Ordering
{
257 (self.vtable_ptr
as *const VTable
).cmp(&(other
.vtable_ptr
as *const VTable
))
261 impl<Dyn
: ?Sized
> PartialOrd
for DynMetadata
<Dyn
> {
263 fn partial_cmp(&self, other
: &Self) -> Option
<crate::cmp
::Ordering
> {
264 Some(self.cmp(other
))
268 impl<Dyn
: ?Sized
> Hash
for DynMetadata
<Dyn
> {
270 fn hash
<H
: Hasher
>(&self, hasher
: &mut H
) {
271 crate::ptr
::hash
::<VTable
, _
>(self.vtable_ptr
, hasher
)