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) {...@@ -7079,8 +7079,6 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
7079 if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {7079 if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
7080 TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);7080 TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
7081 assert(field != nullptr);7081 assert(field != nullptr);
7082 if (!type_has_bits(g, field->type_entry))
7083 return true;
7084 assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);7082 assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);
7085 return const_values_equal(g, union1->payload, union2->payload);7083 return const_values_equal(g, union1->payload, union2->payload);
7086 }7084 }
test/stage1/behavior.zig+1
...@@ -56,6 +56,7 @@ comptime {...@@ -56,6 +56,7 @@ comptime {
56 _ = @import("behavior/bugs/6456.zig");56 _ = @import("behavior/bugs/6456.zig");
57 _ = @import("behavior/bugs/6781.zig");57 _ = @import("behavior/bugs/6781.zig");
58 _ = @import("behavior/bugs/6850.zig");58 _ = @import("behavior/bugs/6850.zig");
59 _ = @import("behavior/bugs/7047.zig");
59 _ = @import("behavior/bugs/394.zig");60 _ = @import("behavior/bugs/394.zig");
60 _ = @import("behavior/bugs/421.zig");61 _ = @import("behavior/bugs/421.zig");
61 _ = @import("behavior/bugs/529.zig");62 _ = @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}