Commit 32e89a98d8

Andrew Kelley <andrew@ziglang.org>
2022-02-27 02:01:12
Sema: implement union value equality at comptime
Still TODO is extern unions.
1 parent e999a92
Changed files (3)
src
test
behavior
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());
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;
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 });