1 #![unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
4 use crate::hash::{Hash, Hasher};
7 #[lang = "pointee_trait"]
9 /// The type for metadata in pointers and references to `Self`.
10 #[lang = "metadata_type"]
11 // NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata`
12 // in `library/core/src/ptr/metadata.rs`
13 // in sync with those here:
14 type Metadata: Copy + Send + Sync + Ord + Hash + Unpin;
17 /// Pointers to types implementing this trait alias are “thin”
20 /// #![feature(ptr_metadata)]
22 /// fn this_never_panics<T: std::ptr::Thin>() {
23 /// assert_eq!(std::mem::size_of::<&T>(), std::mem::size_of::<usize>())
26 #[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
27 // NOTE: don’t stabilize this before trait aliases are stable in the language?
28 pub trait Thin = Pointee<Metadata = ()>;
30 /// Extract the metadata component of a pointer.
31 #[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
33 pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
34 // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
35 // and PtrComponents<T> have the same memory layouts. Only std can make this
37 unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
40 /// Forms a raw pointer from a data address and metadata.
41 #[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
42 #[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
44 pub const fn from_raw_parts<T: ?Sized>(
45 data_address: *const (),
46 metadata: <T as Pointee>::Metadata,
48 // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
49 // and PtrComponents<T> have the same memory layouts. Only std can make this
51 unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.const_ptr }
54 /// Performs the same functionality as [`from_raw_parts`], except that a
55 /// raw `*mut` pointer is returned, as opposed to a raw `*const` pointer.
57 /// See the documentation of [`from_raw_parts`] for more details.
58 #[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
59 #[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
61 pub const fn from_raw_parts_mut<T: ?Sized>(
62 data_address: *mut (),
63 metadata: <T as Pointee>::Metadata,
65 // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
66 // and PtrComponents<T> have the same memory layouts. Only std can make this
68 unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.mut_ptr }
72 pub(crate) union PtrRepr<T: ?Sized> {
73 pub(crate) const_ptr: *const T,
74 pub(crate) mut_ptr: *mut T,
75 pub(crate) components: PtrComponents<T>,
79 pub(crate) struct PtrComponents<T: ?Sized> {
80 pub(crate) data_address: *const (),
81 pub(crate) metadata: <T as Pointee>::Metadata,
84 // Manual impl needed to avoid `T: Copy` bound.
85 impl<T: ?Sized> Copy for PtrComponents<T> {}
87 // Manual impl needed to avoid `T: Clone` bound.
88 impl<T: ?Sized> Clone for PtrComponents<T> {
89 fn clone(&self) -> Self {
94 /// The metadata for a `dyn SomeTrait` trait object type.
95 #[lang = "dyn_metadata"]
96 pub struct DynMetadata<Dyn: ?Sized> {
97 vtable_ptr: &'static VTable,
98 phantom: crate::marker::PhantomData<Dyn>,
101 /// The common prefix of all vtables. It is followed by function pointers for trait methods.
103 /// Private implementation detail of `DynMetadata::size_of` etc.
106 drop_in_place: fn(*mut ()),
111 impl<Dyn: ?Sized> DynMetadata<Dyn> {
112 /// Returns the size of the type associated with this vtable.
114 pub fn size_of(self) -> usize {
115 self.vtable_ptr.size_of
118 /// Returns the alignment of the type associated with this vtable.
120 pub fn align_of(self) -> usize {
121 self.vtable_ptr.align_of
124 /// Returns the size and alignment together as a `Layout`
126 pub fn layout(self) -> crate::alloc::Layout {
127 // SAFETY: the compiler emitted this vtable for a concrete Rust type which
128 // is known to have a valid layout. Same rationale as in `Layout::for_value`.
129 unsafe { crate::alloc::Layout::from_size_align_unchecked(self.size_of(), self.align_of()) }
133 unsafe impl<Dyn: ?Sized> Send for DynMetadata<Dyn> {}
134 unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}
136 impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 f.debug_tuple("DynMetadata").field(&(self.vtable_ptr as *const VTable)).finish()
142 // Manual impls needed to avoid `Dyn: $Trait` bounds.
144 impl<Dyn: ?Sized> Unpin for DynMetadata<Dyn> {}
146 impl<Dyn: ?Sized> Copy for DynMetadata<Dyn> {}
148 impl<Dyn: ?Sized> Clone for DynMetadata<Dyn> {
150 fn clone(&self) -> Self {
155 impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}
157 impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> {
159 fn eq(&self, other: &Self) -> bool {
160 crate::ptr::eq::<VTable>(self.vtable_ptr, other.vtable_ptr)
164 impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
166 fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
167 (self.vtable_ptr as *const VTable).cmp(&(other.vtable_ptr as *const VTable))
171 impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
173 fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
174 Some(self.cmp(other))
178 impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
180 fn hash<H: Hasher>(&self, hasher: &mut H) {
181 crate::ptr::hash::<VTable, _>(self.vtable_ptr, hasher)