From de7279787ff9da73771e4f8a509ae5a7f0eb226a Mon Sep 17 00:00:00 2001 From: riverbl <94326797+riverbl@users.noreply.github.com> Date: Tue, 18 Jan 2022 22:41:19 +0000 Subject: [PATCH 1/2] MultiArrayList: Fix error when struct is 0 sized Also fixes error with ArrayHashMap when both key and value are 0 sized --- lib/std/array_hash_map.zig | 29 +++++++++++++++++ lib/std/multi_array_list.zig | 63 ++++++++++++++++++++++++++++++++---- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/lib/std/array_hash_map.zig b/lib/std/array_hash_map.zig index 7ebafc0a1b4b..efd75a0fee7b 100644 --- a/lib/std/array_hash_map.zig +++ b/lib/std/array_hash_map.zig @@ -2215,6 +2215,35 @@ test "auto store_hash" { try testing.expect(meta.fieldInfo(HasExpensiveEqlUn.Data, .hash).field_type != void); } +test "0 sized key" { + var map = AutoArrayHashMap(u0, i32).init(std.testing.allocator); + defer map.deinit(); + + try testing.expectEqual(map.get(0), null); + + try map.put(0, 5); + try testing.expectEqual(map.get(0), 5); + + try map.put(0, 10); + try testing.expectEqual(map.get(0), 10); + + try testing.expectEqual(map.swapRemove(0), true); + try testing.expectEqual(map.get(0), null); +} + +test "0 sized key and 0 sized value" { + var map = AutoArrayHashMap(u0, u0).init(std.testing.allocator); + defer map.deinit(); + + try testing.expectEqual(map.get(0), null); + + try map.put(0, 0); + try testing.expectEqual(map.get(0), 0); + + try testing.expectEqual(map.swapRemove(0), true); + try testing.expectEqual(map.get(0), null); +} + pub fn getHashPtrAddrFn(comptime K: type, comptime Context: type) (fn (Context, K) u32) { return struct { fn hash(ctx: Context, key: K) u32 { diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index 47d12884df7c..074eb08e7a37 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -16,7 +16,9 @@ const testing = std.testing; /// `.items(.)` to obtain a slice of field values. pub fn MultiArrayList(comptime S: type) type { return struct { - bytes: [*]align(@alignOf(S)) u8 = undefined, + const alignS = if (@alignOf(S) == 0) 1 else @alignOf(S); + + bytes: [*]align(alignS) u8 = undefined, len: usize = 0, capacity: usize = 0, @@ -50,8 +52,8 @@ pub fn MultiArrayList(comptime S: type) type { return .{}; } const unaligned_ptr = self.ptrs[sizes.fields[0]]; - const aligned_ptr = @alignCast(@alignOf(S), unaligned_ptr); - const casted_ptr = @ptrCast([*]align(@alignOf(S)) u8, aligned_ptr); + const aligned_ptr = @alignCast(alignS, unaligned_ptr); + const casted_ptr = @ptrCast([*]align(alignS) u8, aligned_ptr); return .{ .bytes = casted_ptr, .len = self.len, @@ -261,7 +263,7 @@ pub fn MultiArrayList(comptime S: type) type { const other_bytes = gpa.allocAdvanced( u8, - @alignOf(S), + alignS, capacityInBytes(new_len), .exact, ) catch { @@ -339,7 +341,7 @@ pub fn MultiArrayList(comptime S: type) type { assert(new_capacity >= self.len); const new_bytes = try gpa.allocAdvanced( u8, - @alignOf(S), + alignS, capacityInBytes(new_capacity), .exact, ); @@ -398,7 +400,7 @@ pub fn MultiArrayList(comptime S: type) type { return @reduce(.Add, capacity_vector * sizes_vector); } - fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 { + fn allocatedBytes(self: Self) []align(alignS) u8 { return self.bytes[0..capacityInBytes(self.capacity)]; } @@ -621,3 +623,52 @@ test "insert elements" { try testing.expectEqualSlices(u8, &[_]u8{ 1, 2 }, list.items(.a)); try testing.expectEqualSlices(u32, &[_]u32{ 2, 3 }, list.items(.b)); } + +test "0 sized struct field" { + const ally = testing.allocator; + + const Foo = struct { + a: u0, + b: f32, + }; + + var list = MultiArrayList(Foo){}; + defer list.deinit(ally); + + try testing.expectEqualSlices(u0, &[_]u0{}, list.items(.a)); + try testing.expectEqualSlices(f32, &[_]f32{}, list.items(.b)); + + try list.append(ally, .{ .a = 0, .b = 42.0 }); + try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); + try testing.expectEqualSlices(f32, &[_]f32{ 42.0 }, list.items(.b)); + + try list.insert(ally, 0, .{ .a = 0, .b = -1.0 }); + try testing.expectEqualSlices(u0, &[_]u0{ 0, 0 }, list.items(.a)); + try testing.expectEqualSlices(f32, &[_]f32{ -1.0, 42.0 }, list.items(.b)); + + list.swapRemove(list.len - 1); + try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); + try testing.expectEqualSlices(f32, &[_]f32{ -1.0 }, list.items(.b)); +} + +test "0 sized struct" { + const ally = testing.allocator; + + const Foo = struct { + a: u0, + }; + + var list = MultiArrayList(Foo){}; + defer list.deinit(ally); + + try testing.expectEqualSlices(u0, &[_]u0{}, list.items(.a)); + + try list.append(ally, .{ .a = 0 }); + try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); + + try list.insert(ally, 0, .{ .a = 0 }); + try testing.expectEqualSlices(u0, &[_]u0{ 0, 0 }, list.items(.a)); + + list.swapRemove(list.len - 1); + try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); +} From 6a42abc958f9dbb5651425ad9903084431736312 Mon Sep 17 00:00:00 2001 From: riverbl <94326797+riverbl@users.noreply.github.com> Date: Wed, 19 Jan 2022 09:57:41 +0000 Subject: [PATCH 2/2] Fix formatting in multi_array_list.zig --- lib/std/multi_array_list.zig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index 074eb08e7a37..d5cbaaa88e34 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -639,16 +639,16 @@ test "0 sized struct field" { try testing.expectEqualSlices(f32, &[_]f32{}, list.items(.b)); try list.append(ally, .{ .a = 0, .b = 42.0 }); - try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); - try testing.expectEqualSlices(f32, &[_]f32{ 42.0 }, list.items(.b)); + try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); + try testing.expectEqualSlices(f32, &[_]f32{42.0}, list.items(.b)); try list.insert(ally, 0, .{ .a = 0, .b = -1.0 }); try testing.expectEqualSlices(u0, &[_]u0{ 0, 0 }, list.items(.a)); try testing.expectEqualSlices(f32, &[_]f32{ -1.0, 42.0 }, list.items(.b)); list.swapRemove(list.len - 1); - try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); - try testing.expectEqualSlices(f32, &[_]f32{ -1.0 }, list.items(.b)); + try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); + try testing.expectEqualSlices(f32, &[_]f32{-1.0}, list.items(.b)); } test "0 sized struct" { @@ -664,11 +664,11 @@ test "0 sized struct" { try testing.expectEqualSlices(u0, &[_]u0{}, list.items(.a)); try list.append(ally, .{ .a = 0 }); - try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); + try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); try list.insert(ally, 0, .{ .a = 0 }); try testing.expectEqualSlices(u0, &[_]u0{ 0, 0 }, list.items(.a)); list.swapRemove(list.len - 1); - try testing.expectEqualSlices(u0, &[_]u0{ 0 }, list.items(.a)); + try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); }