diff options
| author | Veikka Tuominen <git@vexu.eu> | 2024-06-18 23:07:01 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-18 23:07:01 +0300 |
| commit | 7dc52a367ae6bf7d9adbe72f1d3c34103c3c6a4f (patch) | |
| tree | 4c10fee4af96038ac3325f1817dc73847cc92bf6 /lib/std | |
| parent | 04e08ea883f94d2de7a91daee72ccc9613a18a43 (diff) | |
| parent | 0ffeec4b4d3c0321cac618557e829571fa997881 (diff) | |
| download | zig-7dc52a367ae6bf7d9adbe72f1d3c34103c3c6a4f.tar.gz zig-7dc52a367ae6bf7d9adbe72f1d3c34103c3c6a4f.zip | |
Merge pull request #20343 from rohlem/std-fix-recursive-union-eql
fix `std.testing.expectEqual`, `std.meta.eql` for `comptime`-only unions
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/meta.zig | 22 | ||||
| -rw-r--r-- | lib/std/testing.zig | 26 |
2 files changed, 28 insertions, 20 deletions
diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 0fff0aed3c..85eb6cd4d3 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -757,16 +757,13 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool { }, .Union => |info| { if (info.tag_type) |UnionTag| { - const tag_a = activeTag(a); - const tag_b = activeTag(b); + const tag_a: UnionTag = a; + const tag_b: UnionTag = b; if (tag_a != tag_b) return false; - inline for (info.fields) |field_info| { - if (@field(UnionTag, field_info.name) == tag_a) { - return eql(@field(a, field_info.name), @field(b, field_info.name)); - } - } - return false; + return switch (a) { + inline else => |val, tag| return eql(val, @field(b, @tagName(tag))), + }; } @compileError("cannot compare untagged union type " ++ @typeName(T)); @@ -858,6 +855,15 @@ test eql { try testing.expect(eql(v1, v2)); try testing.expect(!eql(v1, v3)); + + const CU = union(enum) { + a: void, + b: void, + c: comptime_int, + }; + + try testing.expect(eql(CU{ .a = {} }, .a)); + try testing.expect(!eql(CU{ .a = {} }, .b)); } test intToEnum { diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 051b6becee..341161a64b 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -147,18 +147,10 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void { try expectEqual(expectedTag, actualTag); - // we only reach this loop if the tags are equal - inline for (std.meta.fields(@TypeOf(actual))) |fld| { - if (std.mem.eql(u8, fld.name, @tagName(actualTag))) { - try expectEqual(@field(expected, fld.name), @field(actual, fld.name)); - return; - } + // we only reach this switch if the tags are equal + switch (expected) { + inline else => |val, tag| try expectEqual(val, @field(actual, @tagName(tag))), } - - // we iterate over *all* union fields - // => we should never get here as the loop above is - // including all possible values. - unreachable; }, .Optional => { @@ -208,6 +200,16 @@ test "expectEqual.union(enum)" { try expectEqual(a10, a10); } +test "expectEqual union with comptime-only field" { + const U = union(enum) { + a: void, + b: void, + c: comptime_int, + }; + + try expectEqual(U{ .a = {} }, .a); +} + /// This function is intended to be used only in tests. When the formatted result of the template /// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how /// they are not equal, then returns an error. It depends on `expectEqualStrings()` for printing @@ -809,7 +811,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe try expectEqual(expectedTag, actualTag); - // we only reach this loop if the tags are equal + // we only reach this switch if the tags are equal switch (expected) { inline else => |val, tag| { try expectEqualDeep(val, @field(actual, @tagName(tag))); |
