authorgravatar for red.black.liquorice@gmail.comHila Friedman <red.black.liquorice@gmail.com> 2026-04-02 15:11:24+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-02 15:11:24+02:00
log746dd51fafa8cdc8d98500af3b3b4b659c1aef92
treef406c0532716f162451b1a327cd7300d31f40e18
parentf4eecf8d7d4026a9e0ab8986b1c049ad2a0e01fc

Simplify `std.ArrayList.replaceRange` and `std.ArrayList.replaceRangeAssumeCapacity` (#31710)

The implementations of `std.ArrayList.replaceRange` and `std.ArrayList.replaceRangeAssumeCapacity` were needlessly complicated, called `@memcpy` too many times, and left the structure in a semi-modified state in OOM conditions. This commit fixes that. Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31710 Reviewed-by: Andrew Kelley <andrew@ziglang.org> Co-authored-by: Hila Friedman <red.black.liquorice@gmail.com> Co-committed-by: Hila Friedman <red.black.liquorice@gmail.com>

1 files changed, 22 insertions(+), 31 deletions(-)

lib/std/array_list.zig+22-31
......@@ -857,16 +857,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
857857 len: usize,
858858 new_items: []const T,
859859 ) Allocator.Error!void {
860 const after_range = start + len;
861 const range = self.items[start..after_range];
862 if (range.len < new_items.len) {
863 const first = new_items[0..range.len];
864 const rest = new_items[range.len..];
865 @memcpy(range[0..first.len], first);
866 try self.insertSlice(gpa, after_range, rest);
867 } else {
868 self.replaceRangeAssumeCapacity(start, len, new_items);
869 }
860 try self.ensureTotalCapacity(gpa, try addOrOom(self.items.len - len, new_items.len));
861 self.replaceRangeAssumeCapacity(start, len, new_items);
870862 }
871863
872864 /// Grows or shrinks the list as necessary.
......@@ -874,26 +866,20 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
874866 /// Never invalidates element pointers.
875867 ///
876868 /// Asserts the capacity is enough for additional items.
877 pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void {
878 const after_range = start + len;
879 const range = self.items[start..after_range];
880
881 if (range.len == new_items.len)
882 @memcpy(range[0..new_items.len], new_items)
883 else if (range.len < new_items.len) {
884 const first = new_items[0..range.len];
885 const rest = new_items[range.len..];
886 @memcpy(range[0..first.len], first);
887 const dst = self.addManyAtAssumeCapacity(after_range, rest.len);
888 @memcpy(dst, rest);
889 } else {
890 const extra = range.len - new_items.len;
891 @memcpy(range[0..new_items.len], new_items);
892 const src = self.items[after_range..];
893 @memmove(self.items[after_range - extra ..][0..src.len], src);
894 @memset(self.items[self.items.len - extra ..], undefined);
895 self.items.len -= extra;
896 }
869 pub fn replaceRangeAssumeCapacity(
870 self: *Self,
871 start: usize,
872 len: usize,
873 new_items: []const T,
874 ) void {
875 std.debug.assert(self.capacity - self.items.len >= new_items.len -| len);
876
877 const tail = self.items[start + len ..];
878 const vacated = self.items[self.items.len - (len -| new_items.len) ..];
879 self.items.len = self.items.len - len + new_items.len;
880 @memmove(self.items[start + new_items.len ..], tail);
881 @memcpy(self.items[start..][0..new_items.len], new_items);
882 @memset(vacated, undefined);
897883 }
898884
899885 /// Grows or shrinks the list as necessary.
......@@ -902,7 +888,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
902888 ///
903889 /// If the unused capacity is insufficient for additional items,
904890 /// returns `error.OutOfMemory`.
905 pub fn replaceRangeBounded(self: *Self, start: usize, len: usize, new_items: []const T) error{OutOfMemory}!void {
891 pub fn replaceRangeBounded(
892 self: *Self,
893 start: usize,
894 len: usize,
895 new_items: []const T,
896 ) error{OutOfMemory}!void {
906897 if (self.capacity - self.items.len < new_items.len -| len) return error.OutOfMemory;
907898 return replaceRangeAssumeCapacity(self, start, len, new_items);
908899 }