Compiler crashes when using short hand union assignment to a static variable
Zig Version
0.12.0
Steps to Reproduce and Observed Behavior
Assigning a global static union by short hand syntax crashes the compiler.
Steps to reproduce:
- Setup a fresh project with
zig init - Replace the content of
src/root.zigwith:
const Tagged = union(enum) {
foo: i32,
};
var global: Tagged = undefined;
pub fn crash() void {
global = .{ .foo = 12 };
}
test "crash" {
crash();
}
- Run the tests with
zig build test.
This gives an output looking something like:
error: the following command exited with error code 3:
D:\Applications\zig\zig.exe test -ODebug -Mroot=D:\projects\zig\reproduce-bug\src\root.zig --cache-dir D:\projects\zig\reproduce-bug\zig-cache --global-cache-dir C:\Users\rhine\AppData\Local\zig --name test --listen=-
Build Summary: 2/5 steps succeeded; 1 failed (disable with --summary none)
test transitive failure
└─ run test transitive failure
└─ zig test Debug native failure
error: the following build command failed with exit code 1:
D:\projects\zig\reproduce-bug\zig-cache\o\b2c2cfa5d27c618976d3927e50c506c1\build.exe D:\Applications\zig\zig.exe D:\projects\zig\reproduce-bug D:\projects\zig\reproduce-bug\zig-cache C:\Users\rhine\AppData\Local\zig --seed 0x321ea57b -Z0e1afd19c2da345a test
If the static variable is moved into the crash function it works fine.
pub fn crash() void {
var global: Tagged = undefined;
global = .{ .foo = 12 };
}
Workaround
Leaving it static but using the full name of the union type works fine.
pub fn crash() void {
global = Tagged{ .foo = 12 };
}
Tested using versions
I've tested this on 0.12.0 on both Windows and Mac, using x86_64 and aarch64 builds respectively. I've also tested this with zig-0.13.0-dev.46+3648d7df1 giving the same result using the same targets as stated for 0.12.0.
This used to work in version: 0.12.0-dev.1349+fa022d1ec
Expected Behavior
Successful compilation. Or an error message if it is intentional.
The crash is indeed in the frontend:
$ stage4/bin/zig test test.zig
thread 1626033 panic: reached unreachable code
Analyzing test.zig: test.zig:crash
%10 = dbg_stmt(2, 5)
%11 = decl_ref("global") token_offset:8:5 to :8:11
%12 = opt_eu_base_ptr_init(%11) node_offset:8:14 to :8:28
> %13 = struct_init_field_ptr(%12, "foo") node_offset:8:24 to :8:26
%14 = int(12)
%15 = store_node(%13, %14) node_offset:8:24 to :8:26
%16 = validate_ptr_struct_init({
%13 = struct_init_field_ptr(%12, "foo") node_offset:8:24 to :8:26
}) node_offset:8:14 to :8:28
%17 = restore_err_ret_index_unconditional(.none) node_offset:7:1 to :7:7
%18 = ret_implicit(@void_value) token_offset:9:1 to :9:1
For full context, use the command
zig ast-check -t test.zig
/home/andy/dev/zig/src/Sema.zig:30993:27: 0x668a2d0 in storePtrVal (zig)
.runtime_store => unreachable, // use sites check this
^
/home/andy/dev/zig/src/Sema.zig:28289:37: 0x6677059 in unionFieldPtr (zig)
try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty);
^
/home/andy/dev/zig/src/Sema.zig:27710:53: 0x60be7ee in fieldPtr (zig)
const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing);
^
/home/andy/dev/zig/src/Sema.zig:10381:33: 0x65ef06f in zirStructInitFieldPtr (zig)
return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, true);
^
/home/andy/dev/zig/src/Sema.zig:1096:76: 0x60af0fe in analyzeBodyInner (zig)
.struct_init_field_ptr => try sema.zirStructInitFieldPtr(block, inst),
^
/home/andy/dev/zig/src/Sema.zig:892:26: 0x60aaa41 in analyzeFnBody (zig)
sema.analyzeBodyInner(block, body) catch |err| switch (err) {
^
/home/andy/dev/zig/src/Module.zig:4633:23: 0x5d97c56 in analyzeFnBody (zig)
sema.analyzeFnBody(&inner_block, fn_info.body) catch |err| switch (err) {
^
/home/andy/dev/zig/src/Module.zig:3143:32: 0x5b01928 in ensureFuncBodyAnalyzed (zig)
var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
^
/home/andy/dev/zig/src/Compilation.zig:3414:42: 0x5aff442 in processOneJob (zig)
module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
^
/home/andy/dev/zig/src/Compilation.zig:3354:30: 0x5933188 in performAllTheWork (zig)
try processOneJob(comp, work_item, main_progress_node);
^
/home/andy/dev/zig/src/Compilation.zig:2132:31: 0x592ebba in update (zig)
try comp.performAllTheWork(main_progress_node);
^
/home/andy/dev/zig/src/main.zig:4489:24: 0x595fba1 in updateModule (zig)
try comp.update(main_progress_node);
^
/home/andy/dev/zig/src/main.zig:3411:17: 0x59c7e89 in buildOutputType (zig)
updateModule(comp, color) catch |err| switch (err) {
^
/home/andy/dev/zig/src/main.zig:268:31: 0x581006b in mainArgs (zig)
return buildOutputType(gpa, arena, args, .zig_test);
^
/home/andy/dev/zig/src/main.zig:208:20: 0x580cdc5 in main (zig)
return mainArgs(gpa, arena, args);
^
/home/andy/dev/zig/lib/std/start.zig:511:37: 0x580c85e in main (zig)
const result = root.main() catch |err| {
^
???:?:?: 0x7f2c46efafcd in ??? (libc.so.6)
Unwind information for `libc.so.6:0x7f2c46efafcd` was not available, trace may be incomplete
Aborted (core dumped)
Also happens when reassigning const tagged union (#20926)
export fn entry() void {
const Tagged = union(enum) {
foo: i32,
};
const global: Tagged = undefined;
global = .{ .foo = 12 };
}