diff --git a/src/analyze.cpp b/src/analyze.cpp index b53d263539..3ba4fd7928 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3155,22 +3155,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { tag_type->data.enumeration.fields_by_name.init(field_count); tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope; } else if (enum_type_node != nullptr) { - ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node); - if (type_is_invalid(enum_type)) { - union_type->data.unionation.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - if (enum_type->id != ZigTypeIdEnum) { - union_type->data.unionation.resolve_status = ResolveStatusInvalid; - add_node_error(g, enum_type_node, - buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); - return ErrorSemanticAnalyzeFail; - } - if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) { - assert(g->errors.length != 0); - return err; - } - tag_type = enum_type; + tag_type = analyze_type_expr(g, scope, enum_type_node); } else { if (decl_node->type == NodeTypeContainerDecl) { tag_type = nullptr; @@ -3179,6 +3164,20 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { } } if (tag_type != nullptr) { + if (type_is_invalid(tag_type)) { + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + if (tag_type->id != ZigTypeIdEnum) { + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + add_node_error(g, enum_type_node != nullptr ? enum_type_node : decl_node, + buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&tag_type->name))); + return ErrorSemanticAnalyzeFail; + } + if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) { + assert(g->errors.length != 0); + return err; + } covered_enum_fields = heap::c_allocator.allocate(tag_type->data.enumeration.src_field_count); } union_type->data.unionation.tag_type = tag_type; diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig index eac76c9f98..38d23175d0 100644 --- a/test/stage1/behavior/type.zig +++ b/test/stage1/behavior/type.zig @@ -374,3 +374,45 @@ test "Type.Union" { tagged = .{ .unsigned = 1 }; testing.expectEqual(Tag.unsigned, tagged); } + +test "Type.Union from Type.Enum" { + const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = u0, + .fields = &[_]TypeInfo.EnumField{ + .{ .name = "working_as_expected", .value = 0 }, + }, + .decls = &[_]TypeInfo.Declaration{}, + .is_exhaustive = true, + }, + }); + const T = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = Tag, + .fields = &[_]TypeInfo.UnionField{ + .{ .name = "working_as_expected", .field_type = u32 }, + }, + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + _ = T; + _ = @typeInfo(T).Union; +} + +test "Type.Union from regular enum" { + const E = enum { working_as_expected = 0 }; + const T = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = E, + .fields = &[_]TypeInfo.UnionField{ + .{ .name = "working_as_expected", .field_type = u32 }, + }, + .decls = &[_]TypeInfo.Declaration{}, + }, + }); + _ = T; + _ = @typeInfo(T).Union; +}