Unpacker.readArray cannot be instantiated with any type argument, so the "completely custom format" example in the README does not compile.
Cause
readArray passes its type parameter straight through to unpackArray, but the two disagree about what that parameter means:
// src/msgpack.zig:208
pub fn readArray(self: Unpacker, comptime T: type) ![]T {
return unpackArray(self.reader, self.allocator, T);
}
unpackArray expects T to be the slice type — it derives the element type itself via std.meta.Child(NonOptional(T)) and returns T (src/array.zig:71). readArray instead declares ![]T, i.e. it treats T as the element type. Both readings fail:
readArray(u32) → unpackArray computes std.meta.Child(u32) → "Expected pointer, optional, array or vector type, found 'u32'"
readArray([]u32) → unpackArray returns []u32, but the signature promises [][]u32 → "pointer type child 'u32' cannot cast into pointer type child '[]u32'"
Note Packer.writeArray(comptime T, value: []const T) and Unpacker.readArrayInto(comptime T, buffer: []T) both take the element type, so element-type is the consistent convention for the Packer/Unpacker layer.
Reproducer
This is copied verbatim from the "Or you can use a completely custom format" section of README.md:
const Message = struct {
items: []u32,
pub fn msgpackWrite(self: Message, packer: anytype) !void {
try packer.writeArray(u32, self.items);
}
pub fn msgpackRead(unpacker: anytype) !Message {
const items = try unpacker.readArray(u32);
return Message{ .items = items };
}
};
test "README custom format example" {
const data = [_]u8{ 0x93, 0x01, 0x02, 0x03 };
var r = std.Io.Reader.fixed(&data);
_ = try msgpack.decodeLeaky(Message, std.testing.allocator, &r);
}
It fails to compile against main (Zig 0.16.0).
Suggested fix
Keep the element-type convention and pass the slice type down:
pub fn readArray(self: Unpacker, comptime T: type) ![]T {
return unpackArray(self.reader, self.allocator, []T);
}
I confirmed locally that this one-line change makes the README example above compile and pass, with the rest of the suite still green.
Related: Array(T) in src/array.zig:106
The same generic-never-instantiated situation hides two more errors in the Array(T) helper, which nothing in the repo constructs:
msgpackWrite calls packer.writeArray(self.data) with one argument; the method takes two (comptime T, value).
msgpackRead calls unpacker.readArray([]T) and assigns the result to a []T field.
Worth fixing (or deleting) alongside this. The neighbouring String and Binary helpers are fine.
Why CI is green
refAllDecls does not instantiate generic functions, so test { _ = std.testing.refAllDecls(@This()); } in src/msgpack.zig never type-checks either of these. A small smoke test that actually calls every Packer/Unpacker method once would have caught it — I wrote one while investigating and it found exactly these plus #22.
Unpacker.readArraycannot be instantiated with any type argument, so the "completely custom format" example in the README does not compile.Cause
readArraypasses its type parameter straight through tounpackArray, but the two disagree about what that parameter means:unpackArrayexpectsTto be the slice type — it derives the element type itself viastd.meta.Child(NonOptional(T))and returnsT(src/array.zig:71).readArrayinstead declares![]T, i.e. it treatsTas the element type. Both readings fail:readArray(u32)→unpackArraycomputesstd.meta.Child(u32)→ "Expected pointer, optional, array or vector type, found 'u32'"readArray([]u32)→unpackArrayreturns[]u32, but the signature promises[][]u32→ "pointer type child 'u32' cannot cast into pointer type child '[]u32'"Note
Packer.writeArray(comptime T, value: []const T)andUnpacker.readArrayInto(comptime T, buffer: []T)both take the element type, so element-type is the consistent convention for thePacker/Unpackerlayer.Reproducer
This is copied verbatim from the "Or you can use a completely custom format" section of
README.md:It fails to compile against
main(Zig 0.16.0).Suggested fix
Keep the element-type convention and pass the slice type down:
I confirmed locally that this one-line change makes the README example above compile and pass, with the rest of the suite still green.
Related:
Array(T)insrc/array.zig:106The same generic-never-instantiated situation hides two more errors in the
Array(T)helper, which nothing in the repo constructs:msgpackWritecallspacker.writeArray(self.data)with one argument; the method takes two (comptime T,value).msgpackReadcallsunpacker.readArray([]T)and assigns the result to a[]Tfield.Worth fixing (or deleting) alongside this. The neighbouring
StringandBinaryhelpers are fine.Why CI is green
refAllDeclsdoes not instantiate generic functions, sotest { _ = std.testing.refAllDecls(@This()); }insrc/msgpack.zignever type-checks either of these. A small smoke test that actually calls everyPacker/Unpackermethod once would have caught it — I wrote one while investigating and it found exactly these plus #22.