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 17:21:49-05:00
log4d4ab1e69a40fb11d19e93b42a02016f9d009aef
treeca4312aad89b1a198eab033f972ee2882d8ce04b
parent06a3a69e6f38798b1768976520b8db40c9a210bf

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}