# Storing the size in the box?

**URL:** https://internals.rust-lang.org/t/storing-the-size-in-the-box/15005
**Category:** libs
**Created:** [July 11, 2021, 8:37pm UTC](https://internals.rust-lang.org/t/storing-the-size-in-the-box/15005 "2021-07-11T20:37:20Z")
**Posts on this page:** 1
**Showing post:** 3

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [July 12, 2021, 4:03am UTC](https://internals.rust-lang.org/t/storing-the-size-in-the-box/15005/3 "2021-07-12T04:03:31Z")

</div>

It appears I may have backed myself into a corner, actually:

```rust
#![feature(ptr_metadata)]

use {
    erasable::Erasable,
    std::{marker::PhantomData, ptr},
};

#[repr(C)]
pub struct Indyn<Dyn: ?Sized, T: ?Sized = Dyn> {
    phantom: PhantomData<Dyn>,
    metadata: <Dyn as ptr::Pointee>::Metadata,
    inner: T,
}

unsafe impl<Dyn: ?Sized> Erasable for Indyn<Dyn> {
    unsafe fn unerase(this: erasable::ErasedPtr) -> ptr::NonNull<Self> {
        let metadata = ptr::read::<<Dyn as ptr::Pointee>::Metadata>(this.as_ptr() as *mut _);
        let this: *mut Dyn = ptr::from_raw_parts_mut(this.as_ptr() as *mut _, metadata);
        ptr::NonNull::new_unchecked(this as *mut Indyn<Dyn>)
    }

    const ACK_1_1_0: bool = true;
}

```

This _works_, and miri is happy to accept it.

> **Example**
>
> ```rust
> macro_rules! indyn {
> ($t:expr; as $d:ty) => {{
> let t = $t;
> let p: &$d = &t;
> Indyn {
> phantom: PhantomData,
> metadata: ptr::metadata(p),
> inner: t,
> }
> }};
> }
> 
> fn main() {
> let b: Box<Indyn<dyn Any>> = Box::new(indyn!(0usize; as dyn Any));
> println!("type_name: {}", std::any::type_name_of_val(&b));
> println!("size_of : {}", std::mem::size_of_val(&b));
> 
> let thin = erasable::erase(ptr::NonNull::new(Box::into_raw(b)).unwrap());
> println!("type_name: {}", std::any::type_name_of_val(&thin));
> println!("size_of : {}", std::mem::size_of_val(&thin));
> 
> let b: Box<Indyn<dyn Any>> = unsafe { Box::from_raw(Indyn::unerase(thin).as_ptr()) };
> println!("type_name: {}", std::any::type_name_of_val(&b));
> println!("size_of : {}", std::mem::size_of_val(&b));
> 
> dbg!(b.downcast_ref::<usize>());
> }
> 
> ```
> 
> ```rust
> type_name: alloc::boxed::Box<indyn::Indyn<dyn core::any::Any>>
> size_of : 16
> type_name: core::ptr::non_null::NonNull<erasable::priv_in_pub::Erased>
> size_of : 8
> type_name: alloc::boxed::Box<indyn::Indyn<dyn core::any::Any>>
> size_of : 16
> [src\main.rs:63] b.downcast_ref::<usize>() = Some(
> 0,
> )
> 
> ```

Unfortunately...

```rust
error[E0119]: conflicting implementations of trait `erasable::Erasable` for type `Indyn<_>`
  --> src\main.rs:17:1
   |
17 | unsafe impl<Dyn: ?Sized> Erasable for Indyn<Dyn> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `erasable`:
           - impl<T> Erasable for T;

```

the blanket impl of `Erasable` for any sized `T` conflicts with the specific impl for `Indyn`. I still stand by the blanket impl, so I guess arbitrary DST metadata support for `erasable::Thin` will need to wait for both `ptr_metadata` and `min_specialization` 😢

* * *

(I'm sorry-not-sorry; `Indyn` is a pun on "linline")

---

_[View the full topic](https://internals.rust-lang.org/t/storing-the-size-in-the-box/15005)._
