Similarly to the following, and provide a certain compiler support.
#![feature(ptr_metadata)]
#![feature(layout_for_ptr)]
use std::ops::{Deref, DerefMut};
use std::any::Any;
pub struct TraitValue<DynTrait: ?Sized, const MAX_SIZE: usize> {
data: [u8; MAX_SIZE],
metadata: <DynTrait as std::ptr::Pointee>::Metadata,
}
impl<DynTrait: ?Sized, const MAX_SIZE: usize> TraitValue<DynTrait, MAX_SIZE> {
pub fn new(v: &DynTrait) -> Self {
let ptr = v as *const DynTrait;
assert!(unsafe { std::mem::size_of_val_raw(ptr) } <= MAX_SIZE);
let data = unsafe { std::ptr::read(ptr as *const [u8; MAX_SIZE]) };
let metadata = std::ptr::metadata(ptr);
Self {
data,
metadata,
}
}
}
impl<DynTrait: ?Sized, const MAX_SIZE: usize> Drop for TraitValue<DynTrait, MAX_SIZE> {
fn drop(&mut self) {
unsafe { std::ptr::drop_in_place(self.deref_mut() as *mut DynTrait); }
}
}
impl<DynTrait: ?Sized, const MAX_SIZE: usize> Deref for TraitValue<DynTrait, MAX_SIZE> {
type Target = DynTrait;
fn deref(&self) -> &Self::Target {
unsafe { &*std::ptr::from_raw_parts(&self.data as *const _ as *const (), self.metadata) }
}
}
impl<DynTrait: ?Sized, const MAX_SIZE: usize> DerefMut for TraitValue<DynTrait, MAX_SIZE> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *std::ptr::from_raw_parts_mut(&mut self.data as *mut _ as *mut (), self.metadata) }
}
}
struct Foo {}
impl Drop for Foo {
fn drop(&mut self) {
println!("Drop");
}
}
fn main() {
let x = Foo {};
let mut z = TraitValue::<dyn Any, 10usize>::new(&x as &dyn Any);
std::mem::forget(x);
println!("Test drop trait");
drop(z);
}