zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 32e89a98d82c0f4505a3f3d4cd72e7db2eadfbb9 (tree)
parent e999a925fade363886538722df7605b01da220d1
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Sat, 26 Feb 2022 18:01:12 -0700

Sema: implement union value equality at comptime

Still TODO is extern unions.

Diffstat:
Msrc/type.zig | 8++++++++
Msrc/value.zig | 19+++++++++++++++++++
Mtest/behavior/union.zig | 2--
3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/src/type.zig b/src/type.zig @@ -2934,6 +2934,14 @@ pub const Type = extern union { }; } + /// Asserts the type is a union; returns the tag type, even if the tag will + /// not be stored at runtime. + pub fn unionTagTypeHypothetical(ty: Type) Type { + const union_obj = ty.cast(Payload.Union).?.data; + assert(union_obj.haveFieldTypes()); + return union_obj.tag_ty; + } + pub fn unionFields(ty: Type) Module.Union.Fields { const union_obj = ty.cast(Payload.Union).?.data; assert(union_obj.haveFieldTypes()); diff --git a/src/value.zig b/src/value.zig @@ -1902,6 +1902,25 @@ pub const Value = extern union { } return true; }, + .@"union" => { + const a_union = a.castTag(.@"union").?.data; + const b_union = b.castTag(.@"union").?.data; + switch (ty.containerLayout()) { + .Packed, .Extern => { + // In this case, we must disregard mismatching tags and compare + // based on the in-memory bytes of the payloads. + @panic("TODO implement comparison of extern union values"); + }, + .Auto => { + const tag_ty = ty.unionTagTypeHypothetical(); + if (!a_union.tag.eql(b_union.tag, tag_ty)) { + return false; + } + const active_field_ty = ty.unionFieldType(a_union.tag); + return a_union.val.eql(b_union.val, active_field_ty); + }, + } + }, else => {}, } else if (a_tag == .null_value or b_tag == .null_value) { return false; diff --git a/test/behavior/union.zig b/test/behavior/union.zig @@ -723,8 +723,6 @@ test "@enumToInt works on unions" { } test "comptime union field value equality" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - const a0 = Setter(Attribute{ .A = false }); const a1 = Setter(Attribute{ .A = true }); const a2 = Setter(Attribute{ .A = false });