-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Open
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviorstage1The process of building from source via WebAssembly and the C backend.The process of building from source via WebAssembly and the C backend.
Milestone
Description
Returning a tagged union from within two nested switch statements can fail with a spurious error message or crash the compiler, depending on precisely how the type information is specified in the code.
This works:
const std = @import("std");
pub fn main() !void {
const Outer = enum { first, second };
const Inner = enum { alpha, beta };
const Action = union(enum) { go: u8, stop };
for (std.enums.values(Outer)) |outer| {
for (std.enums.values(Inner)) |inner| {
const action: Action = switch (outer) { // Note type IS specified here
.first => @as(Action, switch (inner) {
.alpha => .{ .go = 1 }, // Type NOT specified here
.beta => .stop, // Type NOT specified here
}),
.second => .stop, // Type NOT specified here
};
std.debug.print("{}\n", .{action});
}
}
}
This version below (which has insufficient type information) causes a compiler crash (checked with versions 0.8.0 and 0.9.0-dev.656+ba71b96fe on linux x86_64):
const std = @import("std");
pub fn main() !void {
const Outer = enum { first, second };
const Inner = enum { alpha, beta };
const Action = union(enum) { go: u8, stop };
for (std.enums.values(Outer)) |outer| {
for (std.enums.values(Inner)) |inner| {
const action = switch (outer) { // Type NOT specified here
.first => @as(Action, switch (inner) {
.alpha => .{ .go = 1 }, // Type NOT specified here
.beta => .stop, // Type NOT specified here
}),
.second => .stop, // Type NOT specified here
};
std.debug.print("{}\n", .{action});
}
}
}
The error message is:
$ zig run nested_switch_tagged_union_crash.zig
Assertion failed at /home/andy/dev/bootstrap-zig/zig/src/stage1/analyze.cpp:4634 in find_union_type_field. This is a bug in the Zig compiler.thread 5083 panic:
Unable to dump stack trace: debug info stripped
Aborted (core dumped)
The following code does not crash the compiler but the error message appears to be spurious as it says there is no member named '.go' in the union:
const std = @import("std");
pub fn main() !void {
const Outer = enum { first, second };
const Inner = enum { alpha, beta };
const Action = union(enum) { go: u8, stop };
for (std.enums.values(Outer)) |outer| {
for (std.enums.values(Inner)) |inner| {
const action = switch (outer) { // Note type NOT specified here
.first => @as(Action, switch (inner) {
.alpha => Action{ .go = 1 }, // Type IS specified here
.beta => Action.stop, // Type IS specified here
}),
.second => Action.stop, // Type IS specified here
};
std.debug.print("{}\n", .{action});
}
}
}
The output is:
$ zig run nested_switch_tagged_union_fails.zig
./nested_switch_tagged_union_fails.zig:12:39: error: no member named 'go' in enum '@typeInfo(Action).Union.tag_type.?'
.alpha => Action{ .go = 1 },
^
/home/andrew/apps/zig-linux-x86_64-0.8.0/lib/std/start.zig:458:40: note: referenced here
const result = root.main() catch |err| {
^
Metadata
Metadata
Assignees
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviorstage1The process of building from source via WebAssembly and the C backend.The process of building from source via WebAssembly and the C backend.