# Allows trait values that are no larger than the specified size to be assigned on the stack

**URL:** <https://internals.rust-lang.org/t/allows-trait-values-that-are-no-larger-than-the-specified-size-to-be-assigned-on-the-stack/16218>\
**Category:** libs\
**Created:** [February 26, 2022, 2:24pm UTC](https://internals.rust-lang.org/t/allows-trait-values-that-are-no-larger-than-the-specified-size-to-be-assigned-on-the-stack/16218 "2022-02-26T14:24:20Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Qsh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/qsh/32/10418_2.png) [@Qsh](https://internals.rust-lang.org/u/Qsh)\
**Post date:** [February 26, 2022, 2:24pm UTC](https://internals.rust-lang.org/t/allows-trait-values-that-are-no-larger-than-the-specified-size-to-be-assigned-on-the-stack/16218/1 "2022-02-26T14:24:20Z")

</div>

Similarly to the following, and provide a certain compiler support.

```rust
#![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);
}

```

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [February 26, 2022, 4:34pm UTC](https://internals.rust-lang.org/t/allows-trait-values-that-are-no-larger-than-the-specified-size-to-be-assigned-on-the-stack/16218/2 "2022-02-26T16:34:07Z")

</div>

Have you seen [smallbox](https://crates.io/crates/smallbox) and other similar crates?

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [May 27, 2022, 4:34pm UTC](https://internals.rust-lang.org/t/allows-trait-values-that-are-no-larger-than-the-specified-size-to-be-assigned-on-the-stack/16218/3 "2022-05-27T16:34:29Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
