factor out common code out of per-trait implementation

This commit is contained in:
numzero 2026-09-23 21:38:34 +03:00
parent ed66afe4b4
commit 3181644cee

View File

@ -1,14 +1,15 @@
#![feature( #![feature(
ptr_metadata, ptr_metadata,
ptr_as_ref_unchecked, ptr_as_ref_unchecked,
sized_hierarchy,
generic_const_exprs, generic_const_exprs,
inherent_associated_types inherent_associated_types
)] )]
use std::{marker::PhantomData, ops, ptr}; use std::{marker::PhantomData, mem::ManuallyDrop, ops, ptr};
#[repr(C, align(16))] #[repr(C, align(16))]
struct Data([*mut u8; 6]); struct Data([*mut std::ffi::c_void; 6]);
pub struct Dyn<'a, Trait: ?Sized + 'a> { pub struct Dyn<'a, Trait: ?Sized + 'a> {
_phantom1: PhantomData<Trait>, _phantom1: PhantomData<Trait>,
@ -33,6 +34,29 @@ impl<'a, Trait: ?Sized + 'a> Dyn<'a, Trait> {
} }
} }
impl<'a, Trait: ?Sized + 'a> Dyn<'a, Trait>
where
Trait: ptr::Pointee<Metadata = ptr::DynMetadata<Trait>>,
{
/// SAFETY:
/// The pointer must be valid for moving from.
/// The value must fit into `Data` (by size and align).
unsafe fn from_ptr(value: *mut Self::Target) -> Self {
let (data, meta): (_, ptr::DynMetadata<_>) = value.to_raw_parts();
debug_assert!(meta.size_of() <= std::mem::size_of::<Data>());
debug_assert!(meta.align_of() <= std::mem::align_of::<Data>());
let mut ret = Self {
_phantom1: PhantomData,
_phantom2: PhantomData,
meta,
data: Data([ptr::null_mut(); _]),
};
let pdata = ret.data.0.as_mut_ptr();
unsafe { ptr::copy_nonoverlapping(data as *const u8, pdata as *mut u8, meta.size_of()) };
ret
}
}
impl<'a, Trait: ?Sized + 'a> Drop for Dyn<'a, Trait> { impl<'a, Trait: ?Sized + 'a> Drop for Dyn<'a, Trait> {
fn drop(&mut self) { fn drop(&mut self) {
// SAFETY: `self` is valid for writing, and won't be accessed later. // SAFETY: `self` is valid for writing, and won't be accessed later.
@ -62,16 +86,9 @@ where
[(); std::mem::align_of::<Data>() - std::mem::align_of::<Iter>()]:, [(); std::mem::align_of::<Data>() - std::mem::align_of::<Iter>()]:,
{ {
fn from(value: Iter) -> Self { fn from(value: Iter) -> Self {
let (_, meta) = (&value as &Self::Target as *const Self::Target).to_raw_parts(); let mut value = ManuallyDrop::new(value);
let mut ret = Self { let ptr = &mut *value as &mut Self::Target as *mut Self::Target;
_phantom1: PhantomData, unsafe { Self::from_ptr(ptr) }
_phantom2: PhantomData,
meta,
data: Data([std::ptr::null_mut(); _]),
};
let pdata = ret.data.0.as_mut_ptr();
unsafe { (pdata as *mut Iter).write(value) };
ret
} }
} }