authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-11-10 17:55:16+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-10 15:24:41-07:00
log85665386c68d176c839048b55f5249d923087890
treeee1f14e340635f6ee6603f9c3a32a000f238288b
parent2c0caa853359f46be0b72d32def8287c50a3507f

stage1: Fix comparison of unions containing zero-sized types

The code tried to be too smart and skipped the equality (returning true) if the payload type was zero-sized. This optimization is completely wrong when the union payload is a metatype! Fixes #7047

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

src/stage1/analyze.cpp-2
......@@ -7079,8 +7079,6 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
70797079 if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
70807080 TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
70817081 assert(field != nullptr);
7082 if (!type_has_bits(g, field->type_entry))
7083 return true;
70847082 assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);
70857083 return const_values_equal(g, union1->payload, union2->payload);
70867084 }
test/stage1/behavior.zig+1
......@@ -56,6 +56,7 @@ comptime {
5656 _ = @import("behavior/bugs/6456.zig");
5757 _ = @import("behavior/bugs/6781.zig");
5858 _ = @import("behavior/bugs/6850.zig");
59 _ = @import("behavior/bugs/7047.zig");
5960 _ = @import("behavior/bugs/394.zig");
6061 _ = @import("behavior/bugs/421.zig");
6162 _ = @import("behavior/bugs/529.zig");
test/stage1/behavior/bugs/7047.zig created+22
......@@ -0,0 +1,22 @@
1const std = @import("std");
2
3const U = union(enum) {
4 T: type,
5 N: void,
6};
7
8fn S(comptime query: U) type {
9 return struct {
10 fn tag() type {
11 return query.T;
12 }
13 };
14}
15
16test "compiler doesn't consider equal unions with different 'type' payload" {
17 const s1 = S(U{ .T = u32 }).tag();
18 std.testing.expectEqual(u32, s1);
19
20 const s2 = S(U{ .T = u64 }).tag();
21 std.testing.expectEqual(u64, s2);
22}