std/ArrayList: Allow ArrayList(u0)
to be created
#8632
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I encountered this issue when writing a type-generic datastructure: if my datastructure is generic over type
T
and internally has anstd.ArrayList(T)
, then it fails to compile ifT
is zero-sized. It fails to compile because the allocator cannot allocate a slice for zero-sized types (e.g. "error: no align available for type 'void'").Example code, godbolt link with errors
Although
ArrayList(void)
sounds dubious, I think a motivating example is creating aHashSet(Key)
from aHashMap(Key, void)
, which is something the docs specifically mention. The currentstd
implementations store theKey
&Value
pairs next to each other, in AoS form, which sidesteps this issue. However the problem would be encountered when implementing #8363, where the pairs are stored in separate arrays in SoA form.I also wanted to mention that issue #7221 may impact this? I'm not fully sure of the ramifications of making zero-sized types have alignment 1. (Would it just fix this problem at a lower level? Would it break my patch's tests?)
For my implementation, I have
ArrayList(void)
still track the length of the list, but it never allocates additional memory. Thelist.items
sliceptr
is never updated, but thelen
is, so it can still be iterated over withfor
, etc. It setslist.capacity
tomaxInt(usize)
(and never updates it).I also wanted feedback on my code specifically:
ArrayList
the right place to fix this, or should the fix be at theAllocator
level? (That sounds "scarier," more potential for a breaking change?)@sizeOf(T) == 0
the best way to check for zero-sized types? I saw in the docs that comptime-only types, liketype
andcomptime_int
, would also match this test -- but it doesn't make sense to use anArrayList
for them.capacity
tomaxInt(usize)
and never update it, even when callingshrinkAndFree(...)
-- I think this makes sense? But it does violate an implied invariant thatlist.shrinkAndFree(n); list.capacity == n
void
instead ofu0
? (Or are there other cases I should cover?)