zig icon indicating copy to clipboard operation
zig copied to clipboard

Compiler crashes when using short hand union assignment to a static variable

Open Rhineheart opened this issue 1 year ago • 2 comments

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:

  1. Setup a fresh project with zig init
  2. Replace the content of src/root.zig with:
const Tagged = union(enum) {
  foo: i32,
};

var global: Tagged = undefined;

pub fn crash() void {
  global = .{ .foo = 12 };
}

test "crash" {
  crash();
}
  1. 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.

Rhineheart avatar May 01 '24 15:05 Rhineheart

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)

andrewrk avatar May 10 '24 21:05 andrewrk

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 };
}

Vexu avatar Aug 03 '24 19:08 Vexu