authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-16 09:04:11+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-16 09:04:11+02:00
logd84569895c80136d9b081a319301a737f342d251
tree1c054a3ba13f70b92143fbdc4c92f28e47a16eea
parent02e5cb1cd4203219ae753e94c7e14cd18a918b49
signature Commit is signed but in an unrecognized format.

turn panics into compile errors, require at least 1 field in non-exhaustive enum


4 files changed, 25 insertions(+), 24 deletions(-)

doc/langref.html.in+2-5
......@@ -2903,11 +2903,8 @@ test "switch using enum literals" {
29032903 {#link|@intToEnum#} on a non-exhaustive enum cannot fail.
29042904 </p>
29052905 <p>
2906 A switch on a non-exhaustive enum can include a '_' prong with the following properties:
2907 <ul>
2908 <li>makes it a compile error if all the known tag names are not handled by the switch</li>
2909 <li>allows omitting {#syntax#}else{#endsyntax#}</li>
2910 </ul>
2906 A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong
2907 with the difference being that it makes it a compile error if all the known tag names are not handled by the switch.
29112908 </p>
29122909 {#code_begin|test#}
29132910const std = @import("std");
src/analyze.cpp+2-1
......@@ -2560,7 +2560,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25602560
25612561 assert(!enum_type->data.enumeration.fields);
25622562 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2563 if (field_count == 0) {
2563 if (field_count == 0 || (field_count == 1 &&
2564 buf_eql_str(decl_node->data.container_decl.fields.at(0)->data.struct_field.name, "_"))) {
25642565 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
25652566
25662567 enum_type->data.enumeration.src_field_count = field_count;
src/codegen.cpp+5-2
......@@ -5065,8 +5065,11 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
50655065{
50665066 ZigType *enum_type = instruction->target->value->type;
50675067 assert(enum_type->id == ZigTypeIdEnum);
5068 if (enum_type->data.enumeration.non_exhaustive)
5069 zig_panic("TODO @tagName on non-exhaustive enum");
5068 if (enum_type->data.enumeration.non_exhaustive) {
5069 add_node_error(g, instruction->base.source_node,
5070 buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991"));
5071 codegen_report_errors_and_exit(g);
5072 }
50705073
50715074 LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type);
50725075
src/ir.cpp+16-16
......@@ -8183,13 +8183,6 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
81838183 return irb->codegen->invalid_instruction;
81848184 }
81858185 else_prong = prong_node;
8186 if (underscore_prong) {
8187 ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
8188 buf_sprintf("else and '_' prong in switch expression"));
8189 add_error_note(irb->codegen, msg, underscore_prong,
8190 buf_sprintf("'_' prong is here"));
8191 return irb->codegen->invalid_instruction;
8192 }
81938186 } else if (prong_item_count == 1 &&
81948187 prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol &&
81958188 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 *
82018194 return irb->codegen->invalid_instruction;
82028195 }
82038196 underscore_prong = prong_node;
8204 if (else_prong) {
8205 ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
8206 buf_sprintf("else and '_' prong in switch expression"));
8207 add_error_note(irb->codegen, msg, else_prong,
8208 buf_sprintf("else prong is here"));
8209 return irb->codegen->invalid_instruction;
8210 }
82118197 } else {
82128198 continue;
82138199 }
8200 if (underscore_prong && else_prong) {
8201 ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
8202 buf_sprintf("else and '_' prong in switch expression"));
8203 if (underscore_prong == prong_node)
8204 add_error_note(irb->codegen, msg, else_prong,
8205 buf_sprintf("else prong is here"));
8206 else
8207 add_error_note(irb->codegen, msg, underscore_prong,
8208 buf_sprintf("'_' prong is here"));
8209 return irb->codegen->invalid_instruction;
8210 }
82148211 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
82158212
82168213 IrBasicBlock *prev_block = irb->current_basic_block;
......@@ -22357,8 +22354,11 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
2235722354 if (instr_is_comptime(target)) {
2235822355 if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
2235922356 return ira->codegen->invalid_instruction;
22360 if (target->value->type->data.enumeration.non_exhaustive)
22361 zig_panic("TODO @tagName on non-exhaustive enum");
22357 if (target->value->type->data.enumeration.non_exhaustive) {
22358 add_node_error(ira->codegen, instruction->base.source_node,
22359 buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991"));
22360 return ira->codegen->invalid_instruction;
22361 }
2236222362 TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint);
2236322363 ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee;
2236422364 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);