Zig compile error: GenericPoison (access of inactive union field)

Unable to understand the compiler error for below code

const std = @import("std");

// Cache requires a function (lambda) to be called when there's no cache hit and an other function(args_to_u64) that can compute args
// of the function to u64 that becomes the identifier to compare same arguments.
pub fn Cache(lambda: anytype, args_to_u64: fn (anytype) u64) type {
    const lambda_info = @typeInfo(@TypeOf(lambda));
    @compileLog(lambda_info);
    if (lambda_info != .Fn) {
        @compileError("lambda should be a function type");
    }
    const return_type = lambda_info.Fn.return_type orelse @compileError("No return type");
    @compileLog(return_type);
    return struct {
        _inner: std.HashMap(u64, return_type, struct {
            fn hash(_: @This(), key: u64) u64 {
                return key;
            }
            fn eql(_: @This(), a: u64, b: u64) bool {
                return a == b;
            }
        }, 80),
        const Self = @This();
        fn init(allocator: std.mem.Allocator) Cache(lambda, args_to_u64) {
            return Self{ ._inner = std.StringHashMap(return_type).init(allocator) };
        }
        fn get(self: *Self, args: anytype) return_type {
            const key = args_to_u64(args);
            const value = self._inner.get(key) orelse @call(.{}, lambda, args);
            return value;
        }
    };
}

// Below tests addition of two numbers and cache
fn _add(a: u64, b: u64) u64 {
    return a + b;
}
const HashAdd = struct {
    var allocator: std.mem.Allocator = undefined;
    pub fn hash_add(args: anytype) u64 {
        const temp = std.fmt.allocPrint(allocator, "{}:{}", .{ args[0], args[1] }) catch unreachable;
        defer allocator.free(temp);
        return std.hash_map.hashString(temp);
    }
};

test "test_cache" {
    const allocator = std.testing.allocator;
    HashAdd.allocator = allocator;
    var cache = Cache(_add, HashAdd.hash_add).init(allocator);
    const value: u64 = cache.get(.{ 1, 2 });
    try std.testing.expectEqual(3, value);
    cache._inner.deinit();
}

While running the test, zig errors by giving

thread 36050 panic: zig compiler bug: GenericPoison
Unable to dump stack trace: debug info stripped
thread 36049 panic: access of inactive union field
Unable to dump stack trace: debug info stripped
Aborted (core dumped)

If you compile with -Doptimize=Debug, you will likely get debug symbols and a trace of which line is at fault.

It is a zig toolchain bug and I can reproduce it using your code.

zig test using 0.13.0:

thread 3879889 panic: zig compiler bug: GenericPoison
Unable to dump stack trace: debug info stripped

zig test using 0.14.0-dev.2628+5b5c60f43:

error: OutOfMemory

Note that zig build-obj succeeds with both 0.13.0 and 0.14.0-dev

2 Likes

0.13.0 fails but got it working in v0.14.0-dev.2634+b36ea592b

Below are the file changes

It works on 0.13.0 too by making init to return Self.