Skip to content

fix: make Unpacker.readUnion usable - #26

Merged
lalinsky merged 1 commit into
mainfrom
fix/unpacker-read-union
Sep 4, 2026
Merged

fix: make Unpacker.readUnion usable#26
lalinsky merged 1 commit into
mainfrom
fix/unpacker-read-union

Conversation

@lalinsky

@lalinsky lalinsky commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Fixes #22.

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

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

unpackUnion returns !T and already handles the optional case internally, via NonOptional(T) and the ?u16 map-header path. The extra ? makes both readings 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'"

Returning !T matches how readStruct forwards to unpackStruct. Callers wanting the nullable behaviour pass ?U, which unpackUnion already supports — the added test covers both.

Why CI was green

Same reason as #21: refAllDecls does not instantiate generic functions, so nothing ever type-checked this. Reverting the signature makes the new test fail to compile.

I exercised every other method on Packer and Unpacker once each while investigating; this and readArray (#21, PR #25) were the only two that were uninstantiable. Everything else compiles and round trips.

zig build test: 154/154 pass.

readUnion declared `!?T` while unpackUnion returns `!T`, adding one optional
level too many. unpackUnion already handles the optional case internally via
NonOptional(T) and the `?u16` map-header path, so the extra `?` made every
instantiation a type error: `readUnion(U)` could not coerce `U` to `?U`, and
`readUnion(?U)` could not coerce `?U` to `??U`.

Return `!T`, matching how readStruct forwards to unpackStruct. Callers wanting
the nullable behaviour pass `?U`, which already works.

refAllDecls does not instantiate generic functions, so this was never covered.
Add a test that reads both a union and an optional union.
@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 58 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 0d4a73d1-94df-4e46-8bb9-6bfc13937d63

📥 Commits

Reviewing files that changed from the base of the PR and between 893211c and 8060737.

📒 Files selected for processing (1)
  • src/msgpack.zig

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lalinsky
lalinsky merged commit d91e9c6 into main Sep 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant