mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
correct field count
This commit is contained in:
parent
6450736c5f
commit
6c8f01dcde
@ -2569,16 +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);
|
||||
enum_type->data.enumeration.non_exhaustive = false;
|
||||
|
||||
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);
|
||||
@ -2620,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;
|
||||
@ -2628,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) {
|
||||
@ -2649,27 +2667,9 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
buf_sprintf("consider 'union(enum)' here"));
|
||||
}
|
||||
|
||||
AstNode *tag_value = field_node->data.struct_field.value;
|
||||
|
||||
if (buf_eql_str(type_enum_field->name, "_")) {
|
||||
if (decl_node->data.container_decl.init_arg_expr == nullptr) {
|
||||
add_node_error(g, field_node, buf_sprintf("non-exhaustive enum must specify size"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
if (field_count > 1 && log2_u64(field_count - 1) == enum_type->size_in_bits) {
|
||||
add_node_error(g, field_node, buf_sprintf("non-exhaustive enum specifies every value"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
if (field_i != field_count - 1) {
|
||||
add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
if (tag_value != nullptr) {
|
||||
add_node_error(g, 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;
|
||||
continue;
|
||||
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);
|
||||
@ -2681,6 +2681,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *tag_value = field_node->data.struct_field.value;
|
||||
|
||||
if (tag_value != nullptr) {
|
||||
// A user-specified value is available
|
||||
ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
|
||||
@ -3293,7 +3295,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
||||
} else if (enum_type_node != nullptr) {
|
||||
for (uint32_t i = 0; i < tag_type->data.enumeration.src_field_count; i += 1) {
|
||||
TypeEnumField *enum_field = &tag_type->data.enumeration.fields[i];
|
||||
if (!covered_enum_fields[i] && !buf_eql_str(enum_field->name, "_")) {
|
||||
if (!covered_enum_fields[i]) {
|
||||
AstNode *enum_decl_node = tag_type->data.enumeration.decl_node;
|
||||
AstNode *field_node = enum_decl_node->data.container_decl.fields.at(i);
|
||||
ErrorMsg *msg = add_node_error(g, decl_node,
|
||||
|
||||
@ -13,9 +13,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ _,
|
||||
\\ b,
|
||||
\\};
|
||||
\\const C = enum(u1) {
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub export fn entry() void {
|
||||
\\ _ = A;
|
||||
\\ _ = B;
|
||||
\\ _ = C;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:4:5: error: non-exhaustive enum must specify size",
|
||||
|
||||
@ -41,6 +41,7 @@ test "non-exhaustive enum" {
|
||||
.b => {},
|
||||
else => {},
|
||||
}
|
||||
expect(@typeInfo(E).Enum.fields.len == 2);
|
||||
expect(@enumToInt(e) == 1);
|
||||
e = @intToEnum(E, 12);
|
||||
expect(@enumToInt(e) == 12);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user