Possible tagged union bug with zig 0.10.1

I think I may have found a bug in zig 0.10.1 but I’d like to check I’m not missing something. Here’s a stripped down example. NOTE: Since I first posted this I’ve further simplified the example so I’ve updated this post.

const std = @import("std");

const Result = union(enum) {
    val: i32,
    flag,
};

pub fn main() !void {
    switch (check(true)) {
        .flag => std.debug.print("check 1: OK - flag was returned\n", .{}),
        .val => std.debug.print("check 1: *** FAIL***\n", .{}),
    }
    switch (check(false)) {
        .flag => std.debug.print("check 2: *** FAIL***\n", .{}),
        .val => std.debug.print("check 2: OK - val was returned\n", .{}),
    }
}

fn check(opt: bool) Result {
    const result = if (opt)
        Result.flag
    else
        Result{ .val = 123 };
    return result;
}

I expect this to print:

check 1: OK - flag was returned
check 2: OK - val was returned

but I get

check 1: *** FAIL***
check 2: OK - val was returned

However, reversing the order of the “val” and “flag” elements in the “Result” declaration to

const Result = union(enum) {
    flag,
    val: i32,
};

causes the tests to pass. Also, changing the “check” function to this:

fn check(opt: bool) Result {
    return if (opt)
        Result.flag
    else
        Result{ .val = 123 };
}

causes the tests to pass. I’m fairly sure this is a compiler bug but would appreciate it if anyone more familiar with Zig than me could confirm it.

Since posting the above I’ve found a workaround to the problem. Rather than edit the post yet again I thought it would be easier to post it as a reply. The solution is to explicitly declare the type of the “result” constant, i.e. change the “check” function to:

fn check(opt: bool) Result {
    const result: Result = if (opt)
        Result.flag
    else
        Result{ .val = 123 };
    return result;

So it appears there is a bug with the type inference in Zig. I’ll try to post a bug report.

Run your example on latest (unstable) Zig, and it works as intended, so the bug was fixed in the meantime.

I think this might have been the related Issue, but it’s just a guess: Miscompilations with union and switch with inferred type · Issue #15122 · ziglang/zig · GitHub

Thanks, @kristoff, both for confirming the bug and for checking that it has been fixed. In that case I won’t report it to avoid a needless bug report.