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:
-
- - makes it a compile error if all the known tag names are not handled by the switch
- - allows omitting {#syntax#}else{#endsyntax#}
-
+ 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