Skip to content

Regression in std.enums.directEnumArray when using a tagged union with multiple zero-bit fields as the Data type #22904

@knutwalker

Description

@knutwalker

Zig Version

0.14.0-dev.3223+13ad984b1

Steps to Reproduce and Observed Behavior

const std = @import("std");

pub fn main() !void {
    const Key = enum { a };
    const Value = union(enum) { x, y };

    _ = std.enums.directEnumArray(Key, Value, 0, .{ .a = .x });
}

This fails to compile:

$ zig build
/Users/knut/.local/share/zvm/master/lib/std/enums.zig:124:68: error: expected type 'enums.EnumFieldStruct(main.main.Key,main.main.Value,null)', found 'enums.EnumFieldStruct(main.main.Key,main.main.Value,null)'
    return directEnumArrayDefault(E, Data, null, max_unused_slots, init_values);
                                                                   ^~~~~~~~~~~
/Users/knut/.local/share/zvm/master/lib/std/enums.zig:27:12: note: struct declared here (2 times)
    return @Type(.{ .@"struct" = .{
           ^~~~~
/Users/knut/.local/share/zvm/master/lib/std/enums.zig:158:33: note: parameter type declared here
    init_values: EnumFieldStruct(E, Data, default),
                 ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~

However, it succeeds in 0.13:

$ zig version
0.13.0
$ zig build && echo "ok"
ok

some investigation

  • Using a tagged union with at least two zero-bit fields is important here. The following values for Value all succeed (without changes to the rest of the example above):

    • union(enum) { x }
    • union(enum) { x, y: i32 }
    • union(enum) { x, y, z: i32 }
    • union(enum) { x, y: i32, z }
    • enum { x }
    • enum { x, y }
  • The following values for Value all fail to compile with the same error, i.e. any zero-bit type triggers the regression:

    • union(enum) { x: void, y }
    • union(enum) { x: u0, y }
    • union(enum) { x: [0]i32, y }
    • union(enum) { x: [1]u0, y }
    • union(enum) { x: enum { z }, y }
    • union(enum) { x: struct {}, y }
    • union(enum) { x: struct { z: void }, y }
    • union(enum) { x: union {}, y }
    • union(enum) { x: union { z: void }, y }
  • Using directEnumArrayDefault directly works, this compiles:

    _ = std.enums.directEnumArrayDefault(Key, Value, null, 0, .{ .a = .x });
  • Interestingly, using just directEnumArray afterwards will now work as well, this compiles:
    _ = std.enums.directEnumArrayDefault(Key, Value, null, 0, .{ .a = .x });
    _ = std.enums.directEnumArray(Key, Value, 0, .{ .a = .x });

but this still doesn't:

    _ = std.enums.directEnumArray(Key, Value, 0, .{ .a = .x });
    _ = std.enums.directEnumArrayDefault(Key, Value, null, 0, .{ .a = .x });

Expected Behavior

no compilation error

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorregressionIt worked in a previous version of Zig, but stopped working.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions