Preface: I renamed acquire
/release
to allocate
/deallocate
, to be closer to the Allocator API.
@CAD97 I tried adding support for converting from Box<T, StorageA>
to Box<T, StorageB>
, and given that T
can be !Sized
at that point, this required me to add an allocate
method to ElementStorage
that only takes the meta-data, not the T
, so you were spot on regarding this comment.
With regard to the exact hierarchy of traits; I am not sure.
At some point in the discussion I was afraid that each data-structure would require a unique trait API. I'm very happy that I managed to distill down the requirements to end up with the 2x2 matrix (Single vs Multi and Element vs Range). It's entirely possible that further simplification is still available... but I am not sure if it's possible, or even desirable:
- I don't think that Single vs Multi should be erased:
- There's a strong semantic difference since Single doesn't keep track of whether it's "occupied" or not. I am slightly uncomfortable smoothing it out.
- This difference has repercussions on the implementation: Multi requires extra tracking which is just overhead for Single, so a given storage is generally specialized for one or the other anyway -- the only exception being the allocators.
- Unification of Element vs Range is even more complicated. Differences are:
-
T: ?Sized + Pointee
vsT
: yet, if considering the range as a single Element, this should work. -
MaybeUninit
: in the case of Range storage. If we change the signature ofresolve
(gonna steal that name...) to going fromHandle<T>
toNonNull<MaybeUninit<T>>
, then it would be smoothed. -
type Capacity
. This latter is critical, it's how aVec<u8, inline::SingleRangeStorage<u8, [u8; 31]>>
can take only 32 bytes. At the same time, there's noCapacity
for Element Storage; it's meaningless.
-
I can see building a hierarchy like:
-
Storage
:Handle<T>
,deallocate
, andresolve
.-
ElementStorage
:destroy
convenience method.-
SingleElementStorage
:allocate
, andcreate
convenience method. -
MultiElementStorage
:allocate
, andcreate
convenience method.
-
-
RangeStorage
:Capacity
,try_grow
, andtry_shrink
.-
SingleRangeStorage
:allocate
. -
MultiRangeStorage
:allocate
.
-
-
However I find the Storage
trait rather... pointless, on its own? I don't have any usecase that would require it right now, though at a guess resolve
may be useful on its own?
Imagining that we paper over the difference between Single
and Multi
, as uncomfortable as this makes me:
-
Storage
:Handle<T>
,deallocate
, andresolve
.-
ElementStorage
:allocate
, and for conveniencecreate
anddestroy
. -
RangeStorage
:Capacity
,allocate
,try_grow
, andtry_shrink
.
-
And imagining that we're okay asking the user to synthetize a SliceMeta<T>
out of thin air just to call allocate
:
-
Storage
:Handle<T>
,allocate
,deallocate
, andresolve
.-
ElementStorage
: conveniencecreate
anddestroy
. -
RangeStorage
:Capacity
,try_grow
, andtry_shrink
.
-
But to reiterate, this seems like shoehorning to me considering that:
- A given container has very specific requirements on the Single/Multi and Element/Range axes, and only requires one combination.
- A given storage is tailored to a very specific case on the Single/Multi axis.
So I could see an advantage in carving out a Storage
with Handle<T>
and resolve
. But any further attempt at simplification seems rather artificial for now.
@RustyYato I don't see how to provide Drop
:
- The storage doesn't keep track of which element is initialized, or not, so doesn't know what to
Drop
. - The handles would need a mutable reference to the storage to be able to drop, which we can't have if we have multiple handles.
- In the case of ranges, only the user knows which elements in the range are initialized or not.
So, I don't see any way to call the destructor of elements because of (3), hence the user would be responsible for that regardless. And I don't see any way to release the memory without extra tracking.
I would say that the Drop
wrapper you ask for is going to be called Box
, Vec
, ... I am not sure there's a good opportunity for an intermediate layer.