authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-12 11:36:26-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-12 11:36:26-07:00
log99657dca1fac04e5015203699e3eb0d656d66b09
treef7265547fc92b7797a6d695ab271f2e92d43f4fd
parentb0edd8752a00ea191decf302d9802b853d85fd4c

Sema: fix comptime equality of extern unions with same tag


2 files changed, 23 insertions(+), 5 deletions(-)

src/value.zig+8-5
...@@ -2122,19 +2122,22 @@ pub const Value = extern union {...@@ -2122,19 +2122,22 @@ pub const Value = extern union {
2122 const b_union = b.castTag(.@"union").?.data;2122 const b_union = b.castTag(.@"union").?.data;
2123 switch (ty.containerLayout()) {2123 switch (ty.containerLayout()) {
2124 .Packed, .Extern => {2124 .Packed, .Extern => {
2125 // In this case, we must disregard mismatching tags and compare2125 const tag_ty = ty.unionTagTypeHypothetical();
2126 // based on the in-memory bytes of the payloads.2126 if (!a_union.tag.eql(b_union.tag, tag_ty, target)) {
2127 @panic("TODO implement comparison of extern union values");2127 // In this case, we must disregard mismatching tags and compare
2128 // based on the in-memory bytes of the payloads.
2129 @panic("TODO comptime comparison of extern union values with mismatching tags");
2130 }
2128 },2131 },
2129 .Auto => {2132 .Auto => {
2130 const tag_ty = ty.unionTagTypeHypothetical();2133 const tag_ty = ty.unionTagTypeHypothetical();
2131 if (!a_union.tag.eql(b_union.tag, tag_ty, target)) {2134 if (!a_union.tag.eql(b_union.tag, tag_ty, target)) {
2132 return false;2135 return false;
2133 }2136 }
2134 const active_field_ty = ty.unionFieldType(a_union.tag, target);
2135 return a_union.val.eql(b_union.val, active_field_ty, target);
2136 },2137 },
2137 }2138 }
2139 const active_field_ty = ty.unionFieldType(a_union.tag, target);
2140 return a_union.val.eql(b_union.val, active_field_ty, target);
2138 },2141 },
2139 else => {},2142 else => {},
2140 } else if (a_tag == .null_value or b_tag == .null_value) {2143 } else if (a_tag == .null_value or b_tag == .null_value) {
test/behavior/union.zig+15
...@@ -1168,3 +1168,18 @@ test "union with a large struct field" {...@@ -1168,3 +1168,18 @@ test "union with a large struct field" {
1168 var s: S = undefined;1168 var s: S = undefined;
1169 U.foo(U{ .s = s });1169 U.foo(U{ .s = s });
1170}1170}
1171
1172test "comptime equality of extern unions with same tag" {
1173 const S = struct {
1174 const U = extern union {
1175 a: i32,
1176 b: f32,
1177 };
1178 fn foo(comptime x: U) i32 {
1179 return x.a;
1180 }
1181 };
1182 const a = S.U{ .a = 1234 };
1183 const b = S.U{ .a = 1234 };
1184 try expect(S.foo(a) == S.foo(b));
1185}