diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-01-17 14:26:12 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-17 14:26:12 -0500 |
| commit | b5ac079f88e9098ea9c95356518820a5c3fb42a8 (patch) | |
| tree | e4028947b688f53a5387b6b3e0b454090ee240dc /src/analyze.cpp | |
| parent | d9be6e5dc693fcbcb5f4c343a3d2b0b9fc786e25 (diff) | |
| parent | 39f92a9ee4ea109628e1f7d5a65bb53575e53194 (diff) | |
| download | zig-b5ac079f88e9098ea9c95356518820a5c3fb42a8.tar.gz zig-b5ac079f88e9098ea9c95356518820a5c3fb42a8.zip | |
Merge pull request #4191 from Vexu/non-exhaustive-enums
Implement non-exhaustive enums
Diffstat (limited to 'src/analyze.cpp')
| -rw-r--r-- | src/analyze.cpp | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index b7838003c8..e064677a09 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2569,15 +2569,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { return ErrorSemanticAnalyzeFail; } - enum_type->data.enumeration.src_field_count = field_count; - enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); - enum_type->data.enumeration.fields_by_name.init(field_count); - Scope *scope = &enum_type->data.enumeration.decls_scope->base; - HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; - occupied_tag_values.init(field_count); - ZigType *tag_int_type; if (enum_type->data.enumeration.layout == ContainerLayoutExtern) { tag_int_type = get_c_int_type(g, CIntTypeInt); @@ -2619,6 +2612,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { } } + enum_type->data.enumeration.non_exhaustive = false; enum_type->data.enumeration.tag_int_type = tag_int_type; enum_type->size_in_bits = tag_int_type->size_in_bits; enum_type->abi_size = tag_int_type->abi_size; @@ -2627,6 +2621,31 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { BigInt bi_one; bigint_init_unsigned(&bi_one, 1); + AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1); + if (buf_eql_str(last_field_node->data.struct_field.name, "_")) { + field_count -= 1; + if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) { + add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + if (decl_node->data.container_decl.init_arg_expr == nullptr) { + add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + if (last_field_node->data.struct_field.value != nullptr) { + add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + enum_type->data.enumeration.non_exhaustive = true; + } + + enum_type->data.enumeration.src_field_count = field_count; + enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); + enum_type->data.enumeration.fields_by_name.init(field_count); + + HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; + occupied_tag_values.init(field_count); + TypeEnumField *last_enum_field = nullptr; for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { @@ -2648,6 +2667,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { buf_sprintf("consider 'union(enum)' here")); } + if (buf_eql_str(type_enum_field->name, "_")) { + add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field); if (field_entry != nullptr) { ErrorMsg *msg = add_node_error(g, field_node, |
