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 andusize
for slices, but they would need to be appropriately typed if we wished to derive slice-length or v-tables for them. Thestorage-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
?