diff --git a/src/lib.rs b/src/lib.rs index 77dd241..6fe9d08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, @@ -33,6 +34,29 @@ impl<'a, Trait: ?Sized + 'a> Dyn<'a, Trait> { } } +impl<'a, Trait: ?Sized + 'a> Dyn<'a, Trait> +where + Trait: ptr::Pointee>, +{ + /// 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::()); + debug_assert!(meta.align_of() <= std::mem::align_of::()); + 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::() - std::mem::align_of::()]:, { 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) } } }