Commit d84569895c
Changed files (4)
doc/langref.html.in
@@ -2903,11 +2903,8 @@ test "switch using enum literals" {
{#link|@intToEnum#} on a non-exhaustive enum cannot fail.
</p>
<p>
- A switch on a non-exhaustive enum can include a '_' prong with the following properties:
- <ul>
- <li>makes it a compile error if all the known tag names are not handled by the switch</li>
- <li>allows omitting {#syntax#}else{#endsyntax#}</li>
- </ul>
+ A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong
+ with the difference being that it makes it a compile error if all the known tag names are not handled by the switch.
</p>
{#code_begin|test#}
const std = @import("std");
src/analyze.cpp
@@ -2560,7 +2560,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
assert(!enum_type->data.enumeration.fields);
uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
- if (field_count == 0) {
+ if (field_count == 0 || (field_count == 1 &&
+ buf_eql_str(decl_node->data.container_decl.fields.at(0)->data.struct_field.name, "_"))) {
add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
enum_type->data.enumeration.src_field_count = field_count;
src/codegen.cpp
@@ -5065,8 +5065,11 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
{
ZigType *enum_type = instruction->target->value->type;
assert(enum_type->id == ZigTypeIdEnum);
- if (enum_type->data.enumeration.non_exhaustive)
- zig_panic("TODO @tagName on non-exhaustive enum");
+ if (enum_type->data.enumeration.non_exhaustive) {
+ add_node_error(g, instruction->base.source_node,
+ buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991"));
+ codegen_report_errors_and_exit(g);
+ }
LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type);
src/ir.cpp
@@ -8183,13 +8183,6 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
return irb->codegen->invalid_instruction;
}
else_prong = prong_node;
- if (underscore_prong) {
- ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
- buf_sprintf("else and '_' prong in switch expression"));
- add_error_note(irb->codegen, msg, underscore_prong,
- buf_sprintf("'_' prong is here"));
- return irb->codegen->invalid_instruction;
- }
} else if (prong_item_count == 1 &&
prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol &&
buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) {
@@ -8201,16 +8194,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
return irb->codegen->invalid_instruction;
}
underscore_prong = prong_node;
- if (else_prong) {
- ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
- buf_sprintf("else and '_' prong in switch expression"));
- add_error_note(irb->codegen, msg, else_prong,
- buf_sprintf("else prong is here"));
- return irb->codegen->invalid_instruction;
- }
} else {
continue;
}
+ if (underscore_prong && else_prong) {
+ ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
+ buf_sprintf("else and '_' prong in switch expression"));
+ if (underscore_prong == prong_node)
+ add_error_note(irb->codegen, msg, else_prong,
+ buf_sprintf("else prong is here"));
+ else
+ add_error_note(irb->codegen, msg, underscore_prong,
+ buf_sprintf("'_' prong is here"));
+ return irb->codegen->invalid_instruction;
+ }
ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
IrBasicBlock *prev_block = irb->current_basic_block;
@@ -22357,8 +22354,11 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
if (instr_is_comptime(target)) {
if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
- if (target->value->type->data.enumeration.non_exhaustive)
- zig_panic("TODO @tagName on non-exhaustive enum");
+ if (target->value->type->data.enumeration.non_exhaustive) {
+ add_node_error(ira->codegen, instruction->base.source_node,
+ buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991"));
+ return ira->codegen->invalid_instruction;
+ }
TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint);
ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee;
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);