Skip to content

Commit a3faf7c

Browse files
committed
correct field count
1 parent 6450736 commit a3faf7c

File tree

3 files changed

+37
-28
lines changed

3 files changed

+37
-28
lines changed

src/analyze.cpp

+30-28
Original file line numberDiff line numberDiff line change
@@ -2569,16 +2569,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25692569
return ErrorSemanticAnalyzeFail;
25702570
}
25712571

2572-
enum_type->data.enumeration.src_field_count = field_count;
2573-
enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
2574-
enum_type->data.enumeration.fields_by_name.init(field_count);
2575-
enum_type->data.enumeration.non_exhaustive = false;
2576-
25772572
Scope *scope = &enum_type->data.enumeration.decls_scope->base;
25782573

2579-
HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
2580-
occupied_tag_values.init(field_count);
2581-
25822574
ZigType *tag_int_type;
25832575
if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
25842576
tag_int_type = get_c_int_type(g, CIntTypeInt);
@@ -2620,6 +2612,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
26202612
}
26212613
}
26222614

2615+
enum_type->data.enumeration.non_exhaustive = false;
26232616
enum_type->data.enumeration.tag_int_type = tag_int_type;
26242617
enum_type->size_in_bits = tag_int_type->size_in_bits;
26252618
enum_type->abi_size = tag_int_type->abi_size;
@@ -2628,6 +2621,31 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
26282621
BigInt bi_one;
26292622
bigint_init_unsigned(&bi_one, 1);
26302623

2624+
AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1);
2625+
if (buf_eql_str(last_field_node->data.struct_field.name, "_")) {
2626+
field_count -= 1;
2627+
if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) {
2628+
add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value"));
2629+
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2630+
}
2631+
if (decl_node->data.container_decl.init_arg_expr == nullptr) {
2632+
add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size"));
2633+
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2634+
}
2635+
if (last_field_node->data.struct_field.value != nullptr) {
2636+
add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
2637+
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2638+
}
2639+
enum_type->data.enumeration.non_exhaustive = true;
2640+
}
2641+
2642+
enum_type->data.enumeration.src_field_count = field_count;
2643+
enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
2644+
enum_type->data.enumeration.fields_by_name.init(field_count);
2645+
2646+
HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
2647+
occupied_tag_values.init(field_count);
2648+
26312649
TypeEnumField *last_enum_field = nullptr;
26322650

26332651
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) {
26492667
buf_sprintf("consider 'union(enum)' here"));
26502668
}
26512669

2652-
AstNode *tag_value = field_node->data.struct_field.value;
2653-
26542670
if (buf_eql_str(type_enum_field->name, "_")) {
2655-
if (decl_node->data.container_decl.init_arg_expr == nullptr) {
2656-
add_node_error(g, field_node, buf_sprintf("non-exhaustive enum must specify size"));
2657-
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2658-
}
2659-
if (field_count > 1 && log2_u64(field_count - 1) == enum_type->size_in_bits) {
2660-
add_node_error(g, field_node, buf_sprintf("non-exhaustive enum specifies every value"));
2661-
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2662-
}
2663-
if (field_i != field_count - 1) {
2664-
add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
2665-
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2666-
}
2667-
if (tag_value != nullptr) {
2668-
add_node_error(g, field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
2669-
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2670-
}
2671-
enum_type->data.enumeration.non_exhaustive = true;
2672-
continue;
2671+
add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
2672+
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
26732673
}
26742674

26752675
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) {
26812681
continue;
26822682
}
26832683

2684+
AstNode *tag_value = field_node->data.struct_field.value;
2685+
26842686
if (tag_value != nullptr) {
26852687
// A user-specified value is available
26862688
ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,

test/compile_errors.zig

+6
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1313
\\ _,
1414
\\ b,
1515
\\};
16+
\\const C = enum(u1) {
17+
\\ a,
18+
\\ b,
19+
\\ _,
20+
\\};
1621
\\pub export fn entry() void {
1722
\\ _ = A;
1823
\\ _ = B;
24+
\\ _ = C;
1925
\\}
2026
, &[_][]const u8{
2127
"tmp.zig:4:5: error: non-exhaustive enum must specify size",

test/stage1/behavior/enum.zig

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ test "non-exhaustive enum" {
4141
.b => {},
4242
else => {},
4343
}
44+
expect(@typeInfo(E).Enum.fields.len == 2);
4445
expect(@enumToInt(e) == 1);
4546
e = @intToEnum(E, 12);
4647
expect(@enumToInt(e) == 12);

0 commit comments

Comments
 (0)