Skip to content

Unpacker.readUnion returns !?T but unpackUnion returns !T, so it never compiles #22

Description

@acoustid-bot

Unpacker.readUnion promises one more level of optional than unpackUnion returns, so it cannot be instantiated with any type argument.

// src/msgpack.zig:232
pub fn readUnion(self: Unpacker, comptime T: type) !?T {
    return unpackUnion(self.reader, self.allocator, T);
}

unpackUnion returns !T (src/union.zig:262) — it already handles the optional case internally, via NonOptional(T) and the ?u16 map-header path. Wrapping the result in another ? makes every instantiation a type error:

  • readUnion(U)"error union payload 'U' cannot cast into error union payload '?U'"
  • readUnion(?U)"optional type child 'U' cannot cast into optional type child '?U'"

Reproducer

const U = union(enum) { a: u8 };

test "readUnion" {
    const d = [_]u8{ 0x81, 0xa1, 'a', 0x01 };
    var r = std.Io.Reader.fixed(&d);
    _ = try msgpack.unpacker(&r, std.testing.allocator).readUnion(U);
}

Fails to compile against main (Zig 0.16.0). Substituting ?U fails too.

Suggested fix

Drop the extra optional, matching how readStruct already forwards to unpackStruct:

pub fn readUnion(self: Unpacker, comptime T: type) !T {
    return unpackUnion(self.reader, self.allocator, T);
}

Callers wanting the nullable behaviour then pass ?U explicitly, which unpackUnion already supports.

Scope

I exercised every other method on Packer and Unpacker once each; this and readArray (#21) are the only two that are uninstantiable. Everything else compiles and round-trips. Same root cause for CI missing it: refAllDecls does not instantiate generics.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions