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
This commit is contained in:
LemonBoy 2020-11-10 17:55:16 +01:00 committed by Andrew Kelley
parent 06a3a69e6f
commit 4d4ab1e69a
3 changed files with 23 additions and 2 deletions

View File

@ -7079,8 +7079,6 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
if (bigint_cmp(&union1->tag, &union2->tag) == CmpEQ) {
TypeUnionField *field = find_union_field_by_tag(a->type, &union1->tag);
assert(field != nullptr);
if (!type_has_bits(g, field->type_entry))
return true;
assert(find_union_field_by_tag(a->type, &union2->tag) != nullptr);
return const_values_equal(g, union1->payload, union2->payload);
}

View File

@ -56,6 +56,7 @@ comptime {
_ = @import("behavior/bugs/6456.zig");
_ = @import("behavior/bugs/6781.zig");
_ = @import("behavior/bugs/6850.zig");
_ = @import("behavior/bugs/7047.zig");
_ = @import("behavior/bugs/394.zig");
_ = @import("behavior/bugs/421.zig");
_ = @import("behavior/bugs/529.zig");

View File

@ -0,0 +1,22 @@
const std = @import("std");
const U = union(enum) {
T: type,
N: void,
};
fn S(comptime query: U) type {
return struct {
fn tag() type {
return query.T;
}
};
}
test "compiler doesn't consider equal unions with different 'type' payload" {
const s1 = S(U{ .T = u32 }).tag();
std.testing.expectEqual(u32, s1);
const s2 = S(U{ .T = u64 }).tag();
std.testing.expectEqual(u64, s2);
}