Box like container FixedSizeBox<128, dyn SomeTrait> which can be constructed from type implementing SomeTrait

Viewed 33

I would like to implement a FixedSizeBox which behaves like the Box but owns the memory in which the object is stored. I introduced an additional parameter CAPACITY which defines the size of the memory which the FixedSizeBox will own.

The problem I encounter is that I am unable to use dyn SomeTrait as FixedSizeBox type and call new with a specific type.

Let's assume I have a trait SomeTrait and a struct A which implements that trait.

trait SomeTrait {}
struct A(u8);
impl SomeTrait for A {}

When I would like to store any object which implements SomeTrait in a Box I can write

let mut a: Box<dyn SomeTrait>;
a = Box::new(A { 0: 0 });

For the FixedSizeBox I would like to have the same functionality and implemented it like:

pub struct FixedSizeBox<const CAPACITY: usize, T: ?Sized> {
    _marker: PhantomData<T>,
}

impl<const CAPACITY: usize, T> FixedSizeBox<CAPACITY, T> {
    pub fn new(_: T) -> FixedSizeBox<CAPACITY, T> {
        FixedSizeBox::<CAPACITY, T> {
            _marker: PhantomData,
        }
    }
}

When I use it in the same fashion as the Box the compiler fails:

let mut b: StackBox<128, dyn SomeTrait>;
// assigning a specific type leads to
// mismatched types
// expected struct `StackBox<dyn SomeTrait, 128_usize>`
//    found struct `StackBox<A, {_: usize}>` (rustc E0308)
b = StackBox::new(A { 0: 0 });

I looked into the Box and Rc implementations but was unable to figure out how rust actually realized this. Is there some trait missing?

As a side constraint, I would like to use stable rust. I could figure out that the nightly feature CoerceUnsized

impl<T, U> std::ops::CoerceUnsized<StackBox<U>> for FixedSizeBox<T>
where
    T: std::marker::Unsize<U> + ?Sized,
    U: ?Sized,
{
}

solves the issue but I would like to understand how this is realized in stable rust for Box so that I can apply it to the FixedSizeBox.

1 Answers

Box is in the standard library, and as such it is allowed to use nightly features even on stable versions. You cannot do that without nightly.

Related