mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
@Type for union fixes
This commit is contained in:
parent
771f35c593
commit
acdf1f0bde
103
src/analyze.cpp
103
src/analyze.cpp
@ -2603,16 +2603,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
if (decl_node->type == NodeTypeContainerDecl) {
|
||||
assert(!enum_type->data.enumeration.fields);
|
||||
field_count = (uint32_t)decl_node->data.container_decl.fields.length;
|
||||
if (field_count == 0) {
|
||||
add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
|
||||
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = nullptr;
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
} else {
|
||||
field_count = enum_type->data.enumeration.src_field_count;
|
||||
field_count = enum_type->data.enumeration.src_field_count + enum_type->data.enumeration.non_exhaustive;
|
||||
}
|
||||
|
||||
if (field_count == 0) {
|
||||
add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = nullptr;
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
Scope *scope = &enum_type->data.enumeration.decls_scope->base;
|
||||
@ -3072,18 +3072,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
||||
if (decl_node->type == NodeTypeContainerDecl) {
|
||||
assert(union_type->data.unionation.fields == nullptr);
|
||||
field_count = (uint32_t)decl_node->data.container_decl.fields.length;
|
||||
if (field_count == 0) {
|
||||
add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));
|
||||
union_type->data.unionation.src_field_count = field_count;
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
union_type->data.unionation.src_field_count = field_count;
|
||||
union_type->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(field_count);
|
||||
union_type->data.unionation.fields_by_name.init(field_count);
|
||||
} else {
|
||||
assert(union_type->data.unionation.fields != nullptr);
|
||||
field_count = union_type->data.unionation.src_field_count;
|
||||
assert(field_count == 0 || union_type->data.unionation.fields != nullptr);
|
||||
}
|
||||
|
||||
if (field_count == 0) {
|
||||
add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));
|
||||
union_type->data.unionation.src_field_count = field_count;
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
Scope *scope = &union_type->data.unionation.decls_scope->base;
|
||||
@ -3217,41 +3218,6 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
||||
}
|
||||
assert(field_type_val->special != ConstValSpecialRuntime);
|
||||
union_field->type_val = field_type_val;
|
||||
if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
|
||||
bool field_is_opaque_type;
|
||||
if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
if (field_is_opaque_type) {
|
||||
add_node_error(g, field_node,
|
||||
buf_create_from_str(
|
||||
"opaque types have unknown size and therefore cannot be directly embedded in unions"));
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
switch (type_val_resolve_requires_comptime(g, field_type_val)) {
|
||||
case ReqCompTimeInvalid:
|
||||
if (g->trace_err != nullptr) {
|
||||
g->trace_err = add_error_note(g, g->trace_err, field_node,
|
||||
buf_create_from_str("while checking this field"));
|
||||
}
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
case ReqCompTimeYes:
|
||||
union_type->data.unionation.requires_comptime = true;
|
||||
break;
|
||||
case ReqCompTimeNo:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((err = type_val_resolve_zero_bits(g, field_type_val, union_type, nullptr, &is_zero_bits[i]))) {
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
}
|
||||
|
||||
if (field_node->data.struct_field.value != nullptr && !is_auto_enum) {
|
||||
@ -3261,6 +3227,41 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
||||
}
|
||||
}
|
||||
|
||||
if (union_field->type_val != nullptr) {
|
||||
bool field_is_opaque_type;
|
||||
if ((err = type_val_resolve_is_opaque_type(g, union_field->type_val, &field_is_opaque_type))) {
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
if (field_is_opaque_type) {
|
||||
add_node_error(g, union_field->decl_node,
|
||||
buf_create_from_str(
|
||||
"opaque types have unknown size and therefore cannot be directly embedded in unions"));
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
switch (type_val_resolve_requires_comptime(g, union_field->type_val)) {
|
||||
case ReqCompTimeInvalid:
|
||||
if (g->trace_err != nullptr) {
|
||||
g->trace_err = add_error_note(g, g->trace_err, union_field->decl_node,
|
||||
buf_create_from_str("while checking this field"));
|
||||
}
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
case ReqCompTimeYes:
|
||||
union_type->data.unionation.requires_comptime = true;
|
||||
break;
|
||||
case ReqCompTimeNo:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((err = type_val_resolve_zero_bits(g, union_field->type_val, union_type, nullptr, &is_zero_bits[i]))) {
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
}
|
||||
|
||||
if (create_enum_type) {
|
||||
di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(union_field->name), i);
|
||||
union_field->enum_field = &tag_type->data.enumeration.fields[i];
|
||||
|
@ -26222,14 +26222,19 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
|
||||
assert(payload->type == ir_type_info_get_type(ira, "Union", nullptr));
|
||||
|
||||
ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0);
|
||||
if (layout_value == nullptr)
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
assert(layout_value->special == ConstValSpecialStatic);
|
||||
assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
|
||||
ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
|
||||
|
||||
ZigType *tag_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "tag_type", 1);
|
||||
if (tag_type != nullptr && type_is_invalid(tag_type)) {
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
if (tag_type != nullptr && tag_type->id != ZigTypeIdEnum) {
|
||||
ir_add_error(ira, source_instr, buf_sprintf(
|
||||
"union tag type must be an enum, not %s", type_id_name(tag_type->id)));
|
||||
"expected enum type, found '%s'", type_id_name(tag_type->id)));
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,63 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
|
||||
});
|
||||
|
||||
cases.add("@Type for union with opaque field",
|
||||
\\const TypeInfo = @import("builtin").TypeInfo;
|
||||
\\const Untagged = @Type(.{
|
||||
\\ .Union = .{
|
||||
\\ .layout = .Auto,
|
||||
\\ .tag_type = null,
|
||||
\\ .fields = &[_]TypeInfo.UnionField{
|
||||
\\ .{ .name = "foo", .field_type = @Type(.Opaque) },
|
||||
\\ },
|
||||
\\ .decls = &[_]TypeInfo.Declaration{},
|
||||
\\ },
|
||||
\\});
|
||||
\\export fn entry() void {
|
||||
\\ _ = Untagged{};
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:25: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
|
||||
"tmp.zig:13:17: note: referenced here",
|
||||
});
|
||||
|
||||
cases.add("@Type for union with zero fields",
|
||||
\\const TypeInfo = @import("builtin").TypeInfo;
|
||||
\\const Untagged = @Type(.{
|
||||
\\ .Union = .{
|
||||
\\ .layout = .Auto,
|
||||
\\ .tag_type = null,
|
||||
\\ .fields = &[_]TypeInfo.UnionField{},
|
||||
\\ .decls = &[_]TypeInfo.Declaration{},
|
||||
\\ },
|
||||
\\});
|
||||
\\export fn entry() void {
|
||||
\\ _ = Untagged{};
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:25: error: unions must have 1 or more fields",
|
||||
"tmp.zig:11:17: note: referenced here",
|
||||
});
|
||||
|
||||
cases.add("@Type for exhaustive enum with zero fields",
|
||||
\\const TypeInfo = @import("builtin").TypeInfo;
|
||||
\\const Tag = @Type(.{
|
||||
\\ .Enum = .{
|
||||
\\ .layout = .Auto,
|
||||
\\ .tag_type = u1,
|
||||
\\ .fields = &[_]TypeInfo.EnumField{},
|
||||
\\ .decls = &[_]TypeInfo.Declaration{},
|
||||
\\ .is_exhaustive = true,
|
||||
\\ },
|
||||
\\});
|
||||
\\export fn entry() void {
|
||||
\\ _ = @intToEnum(Tag, 0);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:2:20: error: enums must have 1 or more fields",
|
||||
"tmp.zig:12:9: note: referenced here",
|
||||
});
|
||||
|
||||
cases.add("@Type for tagged union with extra union field",
|
||||
\\const TypeInfo = @import("builtin").TypeInfo;
|
||||
\\const Tag = @Type(.{
|
||||
|
Loading…
Reference in New Issue
Block a user