I'm trying to create a trait similar to the following:
trait MaybeSized {
type Sized;
}
The idea is that MaybeSized is implemented for all types. For sized types, Self::Sized = Self, and for unsized types, Self::Sized = (). I need to implement this without using any unstable features (ie, I assume this is doable using the specialization feature).
If I want to do that and also support projecting into unsized fields, I'd need to change the associated type definition of Projectable::Wrapped<T> to Projectable::Wrapped<T: ?Sized>. However, that would mean that I couldn't implement Projectable for types which don't support wrapping unsized types. E.g.:
My thinking was that, if I could get the proposed MaybeSized trait working, I could instead do:
type Wrapped<U: ?Sized> = MaybeUninit<<U as MaybeSized>::Sized>;
It might seem weird to say that "wrapping an unsized type results in MaybeUninit<()>", but the idea is that, since MaybeUninit doesn't support unsized types, there's no way you could ever try to field project into an unsized type - if the outer type is sized, then all of its fields must be sized too. So this is just a way of making the compiler happy; it'd never actually get used in practice.
I suppose another approach could be to modify Wrapped to be something like:
type Wrapped<T: ?Sized> where /* bound that represents that this type supports wrapping `T` */
For wrapper types which support wrapping unsized inner types, this where bound would be empty (ie, would be satisfied for all T: ?Sized), and for wrapper types which don't, it would be T: Sized. Obviously you can't literally write that - there's no such thing as an "associated where bound" - but I wonder if you could come up with something that has the same effect.