AutoArrayHashMap: Alignment error when key type is single-member enum and value type is void
Zig Version
0.10.0-dev.295+f19b5ecf4
Steps to Reproduce
This occurs when the AutoArrayHashMap key type is an enum with a single member and the value type is void.
This construct is unlikely to be seen in real-world code, but occurred in a test-case where the hashmap was part of a larger structure taking an enum type argument.
const std = @import("std");
test "alignment error" {
const E = enum { a };
var map = std.AutoArrayHashMap(E, void).init(std.testing.allocator);
defer map.deinit();
}
The compile error disappears if a) another enum member is added, or b) a value type is specified.
Expected Behavior
Successful compilation
Actual Behavior
Fails with
build/lib/zig/std/multi_array_list.zig:19:25: error: alignment must be >= 1
bytes: [*]align(@alignOf(S)) u8 = undefined,
^
build/lib/zig/std/multi_array_list.zig:19:9: note: referenced here
bytes: [*]align(@alignOf(S)) u8 = undefined,
^
./repro.zig:5:44: note: referenced here
var map = std.AutoArrayHashMap(E, void).init(std.testing.allocator);
I agree that align(@alignOf(u0)) ought to work, and that making it work would be a better way to solve this issue.
Maybe @alignOf(u0) should return null rather than 0? @alignOf(T) == n implies that ptr % n must equal 0 if ptr is the address of a variable of type T, but the expression ptr % 0 is undefined, and pointers to zero sized types don't have an address.
Or put another way: u0 has neither an address nor a required alignment, so @alignOf(u0) should be null.
Making @alignOf(u0) return null and allowing align specifiers to accept null to indicate natural alignment would also make the interface consistent between align specifiers and allocAdvanced.
I think using null or 0 for alignment is effectively the same thing according to the way you've described null. ptr % null is undefined in the same mathematical sense that ptr % 0 is undefined. However there's a reason to use 0 to mean "no alignment" - null could potentially have a different meaning than "no alignment" - in some places we use it to mean default alignment, i.e. natural alignment. 0 is unambiguously "undefined alignment" and it could not be mistaken for "natural alignment".
As part of solving this issue, a MultiArrayList with size 0 key type should use a zero-bit type for bytes and capacity as well. In other words, it should effectively become a wrapper around len: usize while preserving the expected API.