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(
ptr_metadata,
ptr_as_ref_unchecked,
sized_hierarchy,
generic_const_exprs,
inherent_associated_types
)]
use std::{marker::PhantomData, ops, ptr};
use std::{marker::PhantomData, mem::ManuallyDrop, ops, ptr};
#[repr(C, align(16))]
struct Data([*mut u8; 6]);
struct Data([*mut std::ffi::c_void; 6]);
pub struct Dyn<'a, Trait: ?Sized + 'a> {
_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> {
fn drop(&mut self) {
// 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>()]:,
{
fn from(value: Iter) -> Self {
let (_, meta) = (&value as &Self::Target as *const Self::Target).to_raw_parts();
let mut ret = Self {
_phantom1: PhantomData,
_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
let mut value = ManuallyDrop::new(value);
let ptr = &mut *value as &mut Self::Target as *mut Self::Target;
unsafe { Self::from_ptr(ptr) }
}
}