You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Union enums, @TagType, and "error: runtime cast to union '…' which has non-void fields" or "error: cast to union '…' must initialize '…' field '…'"
#7532
Closed
kivikakk opened this issue
Dec 23, 2020
· 1 comment
· Fixed by #7538
/Users/kameliya/Code/zig/build-native/lib/zig/std/fmt.zig:386:20: error: cast to union 'UnionEnum' must initialize 'u8' field 'A'
return try value.format(fmt, options, writer);
^
/Users/kameliya/Code/zig/build-native/lib/zig/std/fmt.zig:356:23: note: called from here
try formatType(
^
/Users/kameliya/Code/zig/build-native/lib/zig/std/io/writer.zig:33:34: note: called from here
return std.fmt.format(self, format, args);
^
/Users/kameliya/Code/zig/build-native/lib/zig/std/debug.zig:65:27: note: called from here
nosuspend stderr.print(fmt, args) catch return;
^
./example.zig:14:20: note: called from here
std.debug.print("{}\n", .{@as(@TagType(UnionEnum), x)});
I hit this through many more layers of comptime parameters so it was super cryptic what was happening at first. Now it's pretty clear:
std.fmt.formatType checks if (comptime std.meta.trait.hasFn("format")(T))
this is true even for the @TagType(…) variant, i.e. the enum — it shares its decls with the union (? wording?)
it then calls the user-supplied format function with the enum value as the first argument, which attempts and fails the enum-to-union cast
I think in my mental model I assumed the enum wouldn't also possess the decls, but it's not really clear that they should belong to one and not the other.
I don't know exactly what might've made this easier; perhaps std.fmt.format could check the signature of the format function it's calling? Really bad hack that catches this kind of error:
if (comptimestd.meta.trait.hasFn("format")(T)) {
constformatFn=@typeInfo(@TypeOf(@field(T, "format"))).Fn;
if (formatFn.args.len!=4orformatFn.args[0].arg_type!=T) {
@compileError("NOPE");
}
returntryvalue.format(fmt, options, writer);
}
But maybe this would reject some valid cases I'm not thinking about right now.
The text was updated successfully, but these errors were encountered:
Vexu
added
bug
Observed behavior contradicts documented or intended behavior
stage1
The process of building from source via WebAssembly and the C backend.
labels
Dec 23, 2020
Making the enum type share the scope with the parent union means every
declaration "bleeds" into the enum scope.
Let's mint a fresh empty scope for the enum type.
Thanks to @Vexu for the test case.
Closesziglang#7532
Making the enum type share the scope with the parent union means every
declaration "bleeds" into the enum scope.
Let's mint a fresh empty scope for the enum type.
Thanks to @Vexu for the test case.
Closes#7532
Making the enum type share the scope with the parent union means every
declaration "bleeds" into the enum scope.
Let's mint a fresh empty scope for the enum type.
Thanks to @Vexu for the test case.
Closesziglang#7532
This one caught me by surprise:
zig test example.zig
gives:I hit this through many more layers of comptime parameters so it was super cryptic what was happening at first. Now it's pretty clear:
std.fmt.formatType
checksif (comptime std.meta.trait.hasFn("format")(T))
@TagType(…)
variant, i.e. the enum — it shares its decls with the union (? wording?)format
function with the enum value as the first argument, which attempts and fails the enum-to-union castI think in my mental model I assumed the enum wouldn't also possess the decls, but it's not really clear that they should belong to one and not the other.
I don't know exactly what might've made this easier; perhaps
std.fmt.format
could check the signature of the format function it's calling? Really bad hack that catches this kind of error:But maybe this would reject some valid cases I'm not thinking about right now.
The text was updated successfully, but these errors were encountered: