authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-09-16 03:29:38-06:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-09-16 20:34:01+03:00
log2962be81359a6806f66d220474abcb0b1cf7edf0
treed2e1b8195da94fa1629f1fe28bc12bf69df5aa88
parent281fc10ec5aa8052490b9f951e0ceed1b7008ff4

stage1: fix @Type(.Union) not resolving its tag type

Fixes https://github.com/ziglang/zig/issues/6339

2 files changed, 56 insertions(+), 15 deletions(-)

src/analyze.cpp+14-15
......@@ -3155,30 +3155,29 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
31553155 tag_type->data.enumeration.fields_by_name.init(field_count);
31563156 tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope;
31573157 } else if (enum_type_node != nullptr) {
3158 ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node);
3159 if (type_is_invalid(enum_type)) {
3158 tag_type = analyze_type_expr(g, scope, enum_type_node);
3159 } else {
3160 if (decl_node->type == NodeTypeContainerDecl) {
3161 tag_type = nullptr;
3162 } else {
3163 tag_type = union_type->data.unionation.tag_type;
3164 }
3165 }
3166 if (tag_type != nullptr) {
3167 if (type_is_invalid(tag_type)) {
31603168 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
31613169 return ErrorSemanticAnalyzeFail;
31623170 }
3163 if (enum_type->id != ZigTypeIdEnum) {
3171 if (tag_type->id != ZigTypeIdEnum) {
31643172 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3165 add_node_error(g, enum_type_node,
3166 buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name)));
3173 add_node_error(g, enum_type_node != nullptr ? enum_type_node : decl_node,
3174 buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&tag_type->name)));
31673175 return ErrorSemanticAnalyzeFail;
31683176 }
3169 if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) {
3177 if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) {
31703178 assert(g->errors.length != 0);
31713179 return err;
31723180 }
3173 tag_type = enum_type;
3174 } else {
3175 if (decl_node->type == NodeTypeContainerDecl) {
3176 tag_type = nullptr;
3177 } else {
3178 tag_type = union_type->data.unionation.tag_type;
3179 }
3180 }
3181 if (tag_type != nullptr) {
31823181 covered_enum_fields = heap::c_allocator.allocate<bool>(tag_type->data.enumeration.src_field_count);
31833182 }
31843183 union_type->data.unionation.tag_type = tag_type;
test/stage1/behavior/type.zig+42
......@@ -374,3 +374,45 @@ test "Type.Union" {
374374 tagged = .{ .unsigned = 1 };
375375 testing.expectEqual(Tag.unsigned, tagged);
376376}
377
378test "Type.Union from Type.Enum" {
379 const Tag = @Type(.{
380 .Enum = .{
381 .layout = .Auto,
382 .tag_type = u0,
383 .fields = &[_]TypeInfo.EnumField{
384 .{ .name = "working_as_expected", .value = 0 },
385 },
386 .decls = &[_]TypeInfo.Declaration{},
387 .is_exhaustive = true,
388 },
389 });
390 const T = @Type(.{
391 .Union = .{
392 .layout = .Auto,
393 .tag_type = Tag,
394 .fields = &[_]TypeInfo.UnionField{
395 .{ .name = "working_as_expected", .field_type = u32 },
396 },
397 .decls = &[_]TypeInfo.Declaration{},
398 },
399 });
400 _ = T;
401 _ = @typeInfo(T).Union;
402}
403
404test "Type.Union from regular enum" {
405 const E = enum { working_as_expected = 0 };
406 const T = @Type(.{
407 .Union = .{
408 .layout = .Auto,
409 .tag_type = E,
410 .fields = &[_]TypeInfo.UnionField{
411 .{ .name = "working_as_expected", .field_type = u32 },
412 },
413 .decls = &[_]TypeInfo.Declaration{},
414 },
415 });
416 _ = T;
417 _ = @typeInfo(T).Union;
418}