Add size_of
, align_of
, and layout
methods to DynMetadata
This commit is contained in:
parent
b1e15fa8a2
commit
9ab83b9338
@ -2,7 +2,6 @@
|
||||
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::ptr::NonNull;
|
||||
|
||||
/// FIXME docs
|
||||
#[lang = "pointee_trait"]
|
||||
@ -62,17 +61,48 @@ fn clone(&self) -> Self {
|
||||
/// The metadata for a `dyn SomeTrait` trait object type.
|
||||
#[lang = "dyn_metadata"]
|
||||
pub struct DynMetadata<Dyn: ?Sized> {
|
||||
#[allow(unused)]
|
||||
vtable_ptr: NonNull<()>,
|
||||
vtable_ptr: &'static VTable,
|
||||
phantom: crate::marker::PhantomData<Dyn>,
|
||||
}
|
||||
|
||||
/// The common prefix of all vtables. It is followed by function pointers for trait methods.
|
||||
///
|
||||
/// Private implementation detail of `DynMetadata::size_of` etc.
|
||||
#[repr(C)]
|
||||
struct VTable {
|
||||
drop_in_place: fn(*mut ()),
|
||||
size_of: usize,
|
||||
align_of: usize,
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> DynMetadata<Dyn> {
|
||||
/// Returns the size of the type associated with this vtable.
|
||||
#[inline]
|
||||
pub fn size_of(self) -> usize {
|
||||
self.vtable_ptr.size_of
|
||||
}
|
||||
|
||||
/// Returns the alignment of the type associated with this vtable.
|
||||
#[inline]
|
||||
pub fn align_of(self) -> usize {
|
||||
self.vtable_ptr.align_of
|
||||
}
|
||||
|
||||
/// Returns the size and alignment together as a `Layout`
|
||||
#[inline]
|
||||
pub fn layout(self) -> crate::alloc::Layout {
|
||||
// SAFETY: the compiler emitted this vtable for a concrete Rust type which
|
||||
// is known to have a valid layout. Same rationale as in `Layout::for_value`.
|
||||
unsafe { crate::alloc::Layout::from_size_align_unchecked(self.size_of(), self.align_of()) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<Dyn: ?Sized> Send for DynMetadata<Dyn> {}
|
||||
unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}
|
||||
|
||||
impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("DynMetadata { … }")
|
||||
f.debug_tuple("DynMetadata").field(&(self.vtable_ptr as *const VTable)).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,27 +124,27 @@ impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}
|
||||
impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.vtable_ptr == other.vtable_ptr
|
||||
crate::ptr::eq::<VTable>(self.vtable_ptr, other.vtable_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
|
||||
self.vtable_ptr.cmp(&other.vtable_ptr)
|
||||
(self.vtable_ptr as *const VTable).cmp(&(other.vtable_ptr as *const VTable))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<crate::cmp::Ordering> {
|
||||
Some(self.vtable_ptr.cmp(&other.vtable_ptr))
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
self.vtable_ptr.hash(hasher)
|
||||
crate::ptr::hash::<VTable, _>(self.vtable_ptr, hasher)
|
||||
}
|
||||
}
|
||||
|
@ -505,3 +505,23 @@ fn static_assert_expected_bounds_for_metadata<Meta>()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(bootstrap))]
|
||||
fn dyn_metadata() {
|
||||
#[derive(Debug)]
|
||||
#[repr(align(32))]
|
||||
struct Something([u8; 47]);
|
||||
|
||||
let value = Something([0; 47]);
|
||||
let trait_object: &dyn Debug = &value;
|
||||
let meta = metadata(trait_object);
|
||||
|
||||
assert_eq!(meta.size_of(), 64);
|
||||
assert_eq!(meta.size_of(), std::mem::size_of::<Something>());
|
||||
assert_eq!(meta.align_of(), 32);
|
||||
assert_eq!(meta.align_of(), std::mem::align_of::<Something>());
|
||||
assert_eq!(meta.layout(), std::alloc::Layout::new::<Something>());
|
||||
|
||||
assert!(format!("{:?}", meta).starts_with("DynMetadata(0x"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user