authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-08-27 13:34:02-06:00
committergravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-09-07 06:23:50-06:00
logacdf1f0bde9a07cae2fbe33739f5f4aee7989f7b
tree7ff786a8f58cb7e58d81792d14e0d611ba102709
parent771f35c59381dc6359640d7f572411d24e379240
signaturelock-open Commit is signed but in an unrecognized format.

@Type for union fixes


3 files changed, 114 insertions(+), 51 deletions(-)

src/analyze.cpp+51-50
...@@ -2603,16 +2603,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2603,16 +2603,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2603 if (decl_node->type == NodeTypeContainerDecl) {2603 if (decl_node->type == NodeTypeContainerDecl) {
2604 assert(!enum_type->data.enumeration.fields);2604 assert(!enum_type->data.enumeration.fields);
2605 field_count = (uint32_t)decl_node->data.container_decl.fields.length;2605 field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2606 if (field_count == 0) {
2607 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
2608
2609 enum_type->data.enumeration.src_field_count = field_count;
2610 enum_type->data.enumeration.fields = nullptr;
2611 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2612 return ErrorSemanticAnalyzeFail;
2613 }
2614 } else {2606 } else {
2615 field_count = enum_type->data.enumeration.src_field_count;2607 field_count = enum_type->data.enumeration.src_field_count + enum_type->data.enumeration.non_exhaustive;
2608 }
2609
2610 if (field_count == 0) {
2611 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
2612 enum_type->data.enumeration.src_field_count = field_count;
2613 enum_type->data.enumeration.fields = nullptr;
2614 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2615 return ErrorSemanticAnalyzeFail;
2616 }2616 }
26172617
2618 Scope *scope = &enum_type->data.enumeration.decls_scope->base;2618 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
...@@ -3072,18 +3072,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3072,18 +3072,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3072 if (decl_node->type == NodeTypeContainerDecl) {3072 if (decl_node->type == NodeTypeContainerDecl) {
3073 assert(union_type->data.unionation.fields == nullptr);3073 assert(union_type->data.unionation.fields == nullptr);
3074 field_count = (uint32_t)decl_node->data.container_decl.fields.length;3074 field_count = (uint32_t)decl_node->data.container_decl.fields.length;
3075 if (field_count == 0) {
3076 add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));
3077 union_type->data.unionation.src_field_count = field_count;
3078 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3079 return ErrorSemanticAnalyzeFail;
3080 }
3081 union_type->data.unionation.src_field_count = field_count;3075 union_type->data.unionation.src_field_count = field_count;
3082 union_type->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(field_count);3076 union_type->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(field_count);
3083 union_type->data.unionation.fields_by_name.init(field_count);3077 union_type->data.unionation.fields_by_name.init(field_count);
3084 } else {3078 } else {
3085 assert(union_type->data.unionation.fields != nullptr);
3086 field_count = union_type->data.unionation.src_field_count;3079 field_count = union_type->data.unionation.src_field_count;
3080 assert(field_count == 0 || union_type->data.unionation.fields != nullptr);
3081 }
3082
3083 if (field_count == 0) {
3084 add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields"));
3085 union_type->data.unionation.src_field_count = field_count;
3086 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3087 return ErrorSemanticAnalyzeFail;
3087 }3088 }
30883089
3089 Scope *scope = &union_type->data.unionation.decls_scope->base;3090 Scope *scope = &union_type->data.unionation.decls_scope->base;
...@@ -3217,47 +3218,47 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3217,47 +3218,47 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3217 }3218 }
3218 assert(field_type_val->special != ConstValSpecialRuntime);3219 assert(field_type_val->special != ConstValSpecialRuntime);
3219 union_field->type_val = field_type_val;3220 union_field->type_val = field_type_val;
3220 if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)3221 }
3221 return ErrorSemanticAnalyzeFail;
32223222
3223 bool field_is_opaque_type;3223 if (field_node->data.struct_field.value != nullptr && !is_auto_enum) {
3224 if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {3224 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
3225 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3225 buf_create_from_str("untagged union field assignment"));
3226 return ErrorSemanticAnalyzeFail;3226 add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
3227 }3227 }
3228 if (field_is_opaque_type) {3228 }
3229 add_node_error(g, field_node,
3230 buf_create_from_str(
3231 "opaque types have unknown size and therefore cannot be directly embedded in unions"));
3232 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3233 return ErrorSemanticAnalyzeFail;
3234 }
32353229
3236 switch (type_val_resolve_requires_comptime(g, field_type_val)) {3230 if (union_field->type_val != nullptr) {
3237 case ReqCompTimeInvalid:3231 bool field_is_opaque_type;
3238 if (g->trace_err != nullptr) {3232 if ((err = type_val_resolve_is_opaque_type(g, union_field->type_val, &field_is_opaque_type))) {
3239 g->trace_err = add_error_note(g, g->trace_err, field_node,3233 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3240 buf_create_from_str("while checking this field"));3234 return ErrorSemanticAnalyzeFail;
3241 }3235 }
3242 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3236 if (field_is_opaque_type) {
3243 return ErrorSemanticAnalyzeFail;3237 add_node_error(g, union_field->decl_node,
3244 case ReqCompTimeYes:3238 buf_create_from_str(
3245 union_type->data.unionation.requires_comptime = true;3239 "opaque types have unknown size and therefore cannot be directly embedded in unions"));
3246 break;3240 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3247 case ReqCompTimeNo:3241 return ErrorSemanticAnalyzeFail;
3248 break;3242 }
3249 }
32503243
3251 if ((err = type_val_resolve_zero_bits(g, field_type_val, union_type, nullptr, &is_zero_bits[i]))) {3244 switch (type_val_resolve_requires_comptime(g, union_field->type_val)) {
3245 case ReqCompTimeInvalid:
3246 if (g->trace_err != nullptr) {
3247 g->trace_err = add_error_note(g, g->trace_err, union_field->decl_node,
3248 buf_create_from_str("while checking this field"));
3249 }
3252 union_type->data.unionation.resolve_status = ResolveStatusInvalid;3250 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3253 return ErrorSemanticAnalyzeFail;3251 return ErrorSemanticAnalyzeFail;
3254 }3252 case ReqCompTimeYes:
3253 union_type->data.unionation.requires_comptime = true;
3254 break;
3255 case ReqCompTimeNo:
3256 break;
3255 }3257 }
32563258
3257 if (field_node->data.struct_field.value != nullptr && !is_auto_enum) {3259 if ((err = type_val_resolve_zero_bits(g, union_field->type_val, union_type, nullptr, &is_zero_bits[i]))) {
3258 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,3260 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3259 buf_create_from_str("untagged union field assignment"));3261 return ErrorSemanticAnalyzeFail;
3260 add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
3261 }3262 }
3262 }3263 }
32633264
src/ir.cpp+6-1
...@@ -26222,14 +26222,19 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -26222,14 +26222,19 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
26222 assert(payload->type == ir_type_info_get_type(ira, "Union", nullptr));26222 assert(payload->type == ir_type_info_get_type(ira, "Union", nullptr));
2622326223
26224 ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0);26224 ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0);
26225 if (layout_value == nullptr)
26226 return ira->codegen->invalid_inst_gen->value->type;
26225 assert(layout_value->special == ConstValSpecialStatic);26227 assert(layout_value->special == ConstValSpecialStatic);
26226 assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));26228 assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
26227 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);26229 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
2622826230
26229 ZigType *tag_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "tag_type", 1);26231 ZigType *tag_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "tag_type", 1);
26232 if (tag_type != nullptr && type_is_invalid(tag_type)) {
26233 return ira->codegen->invalid_inst_gen->value->type;
26234 }
26230 if (tag_type != nullptr && tag_type->id != ZigTypeIdEnum) {26235 if (tag_type != nullptr && tag_type->id != ZigTypeIdEnum) {
26231 ir_add_error(ira, source_instr, buf_sprintf(26236 ir_add_error(ira, source_instr, buf_sprintf(
26232 "union tag type must be an enum, not %s", type_id_name(tag_type->id)));26237 "expected enum type, found '%s'", type_id_name(tag_type->id)));
26233 return ira->codegen->invalid_inst_gen->value->type;26238 return ira->codegen->invalid_inst_gen->value->type;
26234 }26239 }
2623526240
test/compile_errors.zig+57
...@@ -10,6 +10,63 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -10,6 +10,63 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
10 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",10 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
11 });11 });
1212
13 cases.add("@Type for union with opaque field",
14 \\const TypeInfo = @import("builtin").TypeInfo;
15 \\const Untagged = @Type(.{
16 \\ .Union = .{
17 \\ .layout = .Auto,
18 \\ .tag_type = null,
19 \\ .fields = &[_]TypeInfo.UnionField{
20 \\ .{ .name = "foo", .field_type = @Type(.Opaque) },
21 \\ },
22 \\ .decls = &[_]TypeInfo.Declaration{},
23 \\ },
24 \\});
25 \\export fn entry() void {
26 \\ _ = Untagged{};
27 \\}
28 , &[_][]const u8{
29 "tmp.zig:2:25: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
30 "tmp.zig:13:17: note: referenced here",
31 });
32
33 cases.add("@Type for union with zero fields",
34 \\const TypeInfo = @import("builtin").TypeInfo;
35 \\const Untagged = @Type(.{
36 \\ .Union = .{
37 \\ .layout = .Auto,
38 \\ .tag_type = null,
39 \\ .fields = &[_]TypeInfo.UnionField{},
40 \\ .decls = &[_]TypeInfo.Declaration{},
41 \\ },
42 \\});
43 \\export fn entry() void {
44 \\ _ = Untagged{};
45 \\}
46 , &[_][]const u8{
47 "tmp.zig:2:25: error: unions must have 1 or more fields",
48 "tmp.zig:11:17: note: referenced here",
49 });
50
51 cases.add("@Type for exhaustive enum with zero fields",
52 \\const TypeInfo = @import("builtin").TypeInfo;
53 \\const Tag = @Type(.{
54 \\ .Enum = .{
55 \\ .layout = .Auto,
56 \\ .tag_type = u1,
57 \\ .fields = &[_]TypeInfo.EnumField{},
58 \\ .decls = &[_]TypeInfo.Declaration{},
59 \\ .is_exhaustive = true,
60 \\ },
61 \\});
62 \\export fn entry() void {
63 \\ _ = @intToEnum(Tag, 0);
64 \\}
65 , &[_][]const u8{
66 "tmp.zig:2:20: error: enums must have 1 or more fields",
67 "tmp.zig:12:9: note: referenced here",
68 });
69
13 cases.add("@Type for tagged union with extra union field",70 cases.add("@Type for tagged union with extra union field",
14 \\const TypeInfo = @import("builtin").TypeInfo;71 \\const TypeInfo = @import("builtin").TypeInfo;
15 \\const Tag = @Type(.{72 \\const Tag = @Type(.{