From d84569895c80136d9b081a319301a737f342d251 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 16 Jan 2020 09:04:11 +0200 Subject: [PATCH] turn panics into compile errors, require at least 1 field in non-exhaustive enum --- doc/langref.html.in | 7 ++----- src/analyze.cpp | 3 ++- src/codegen.cpp | 7 +++++-- src/ir.cpp | 32 ++++++++++++++++---------------- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index dbe98ce70884d888c5a9498b38ceba4eac7d3e65..cac01c5686a5f2cd1471dd7b73fb30a12e2f5148 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2903,11 +2903,8 @@ test "switch using enum literals" { {#link|@intToEnum#} on a non-exhaustive enum cannot fail.

- A switch on a non-exhaustive enum can include a '_' prong with the following properties: -

+ 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.

{#code_begin|test#} const std = @import("std"); diff --git a/src/analyze.cpp b/src/analyze.cpp index 7669e0890b72effe5605ed5a64db25b203907449..a9aaf74a85113eaf5799d7a22bd694b5273a84be 100644 --- a/src/analyze.cpp +++ b/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; diff --git a/src/codegen.cpp b/src/codegen.cpp index 42fd188824274b7379c8f14de206fbb15481d05b..030e892d4530af74c74b51da2f57f44f06494247 100644 --- a/src/codegen.cpp +++ b/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); diff --git a/src/ir.cpp b/src/ir.cpp index 7aa3243c343b301e8161696259b356766975f3fa..43ca01113bdde0f1cfdb83a57120d411236a9694 100644 --- a/src/ir.cpp +++ b/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,15 +8194,19 @@ 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")); + } 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")); - return irb->codegen->invalid_instruction; - } - } else { - continue; + 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); @@ -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); -- 2.54.0