I forget if we ever discussed this, but we could totally have certain iteration operations work in-place, for example:
map could mutate each element in-place if the list is unique and the closure's return type is the same size as the list elementskeepIf on a unique list could track the first and second deletions it encounters, and if there were any keeps in between those, memmove them in-place and repeatI think that already happens for at least map
Assuming input and output type are the same size and list is unique
Why does the result value need the same size? If the input is not used after the operation, the result only needs to be "no larger than the input" in order to reuse the allocation.
That's a really good point. I guess you could compact the list as needed to accomodate the smaller elements
wow, yeah I never thought of that!
if list allocations have or can be given a "capacity" concept, typically a number of elements, then a lot of runtime optimizations get unlocked
You also have to do some more checks around alignment
but yeah, that could be done as well.
Hmm, also for allocation systems where you are required to specify the number of bytes when deallocating, you also need to make sure that you track that as well.
if you're asked to create a list of 2049 U8 values, the allocation probably should be for 4096 bytes, at which point you've got 2047 bytes of spare capacity. Then if you do a take 512, and then map that result into U32, you still can reuse the capacity of that same allocation
since even though the result is larger, it still fits within available capacity
so generally by treating capacity as distinct from length (albeit with capacity being unexposed to the programmer), operations can declare how much space they may need, and that can be checked against capacity.
That said, to make the U8 -> U32 map reuse the same capacity, you'd need to reverse-iterate
or you'd first need to memcpy the input to the end of its capacity in order to forward iterate
without doing either of these, you'd clobber input elements before reading them
Yeah we have a separate capacity field on List and Str since last year. We have added a few tricks to take advantage of that, but there are plenty more tricks left that we haven't done.
Kevin Gillette said:
if you're asked to create a list of 2049 U8 values, the allocation probably should be for 4096 bytes, at which point you've got 2047 bytes of spare capacity. Then if you do a take 512, and then map that result into U32, you still can reuse the capacity of that same allocation
Technically, this isn't guaranteed to be valid (depends on the exact case, almost certainly would work with u8 and u32, but with types with more complex sizes and alignment that may not be the case).
The u8 array could start at an index that would be unaligned for u32s.
But yeah, overall agree there are optimizations to be had, just have to be very careful especially with making them general over all type combinations
actually for those particular examples we'd be fine because our lowest alignment is usize due to the refcount at the beginning
but in theory in the future (with simd) we could have alignments where that would come up!
I know, that is why I depends on the exact case. Didn't want to dive into that, just wanted to clarify the general concern
Last updated: Jun 16 2026 at 16:19 UTC