Should Pointee Metadata be CoerceUnsized?

Background

RFC 2580, and its implementation issue #81513, introduce the Pointee trait, with its Metadata associated type. You can find a discussion here and my own (partial) implementation on crates.io.

Basis for inline storage

My personal interest for this RFC came out of creating an alternative for Allocators, the results of my exploration can be found in the storage-poc repository.

I'll cut to the chase, and rip away the levels of abstractions to present you the InlineBox:

struct InlineBox<T, Storage>
where
     T: ?Sized + Pointee,
{
    storage: MaybeUninit<Storage>,
    metadata: T::Metadata,
}

The idea is simple: a Storage type is used to specify the size and alignment of the storage for the data, and the metadata is stored aside. Using this, one can create an InlineBox<dyn Fn(), [usize; 3]> for example, and since it's Sized it can be used... anywhere: arguments, return types, data members, local variables, etc...

How to implement CoerceUnsized for InlineBox?

There is one missing feature in storage-poc: you can coerce InlineBox<T, Storage> into InlineBox<U, Storage> even if T: Unsize<U> and Box<T> can be coerced into Box<U>.

The intrinsic reason in the above implementation is that while the compiler knows how to coerce a *const T (resp. *mut T) into a *const U (resp. *mut U), it doesn't know how to coerce a T::Metadata into a U::Metadata, and there's no way to teach it as this is not user-defined.

By implementing CoerceUnsized to Pointee::Metadata

An obvious solution, though it has ramifications, is that T::Metadata should be CoerceUnsized<U::Metadata> if the conditions are met.

At the very least, this requires:

  • Typed metadata. The RFC proposes using () for sized types and usize for slices, but they would need to be appropriately typed if we wished to derive slice-length or v-tables for them. The storage-poc crate went with typed metadata.
  • Making these types known to the compiler, since only the compiler can implement appropriate coercion. I believe this means making them #[lang_item].

I may be missing requirements, of course.

Or not?

There may be other ways to implement InlineBox, of course, and there may be medium grounds.

For example, another solution is to open up the implementation of CoerceUnsized, allowing the invocation of user code. In storage-poc, the coerce function is implemented without issue.

Should Pointee Metadata be CoerceUnsized?

I believe that the direction about implementing CoerceUnsized for InlineBox should be solved in order to inform whether Pointee::Metadata should implement CoerceUnsized or not.

Pointee::Metadata actually implementing CoerceUnsized can be left for future work; however should it be necessary it would require that Metadata be strongly typed -- not just () or usize -- which be must be decided before stabilization of RFC 2580.


So, how would you go about implementing CoerceUnsized for InlineBox?

1 Like