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" {...@@ -2903,11 +2903,8 @@ test "switch using enum literals" {
2903 {#link|@intToEnum#} on a non-exhaustive enum cannot fail.2903 {#link|@intToEnum#} on a non-exhaustive enum cannot fail.
2904 </p>2904 </p>
2905 <p>2905 <p>
2906 A switch on a non-exhaustive enum can include a '_' prong with the following properties:2906 A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong
2907 <ul>2907 with the difference being that it makes it a compile error if all the known tag names are not handled by the switch.
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>
2911 </p>2908 </p>
2912 {#code_begin|test#}2909 {#code_begin|test#}
2913const std = @import("std");2910const std = @import("std");
src/analyze.cpp+2-1
...@@ -2560,7 +2560,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2560,7 +2560,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25602560
2561 assert(!enum_type->data.enumeration.fields);2561 assert(!enum_type->data.enumeration.fields);
2562 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;2562 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, "_"))) {
2564 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));2565 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
25652566
2566 enum_type->data.enumeration.src_field_count = field_count;2567 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...@@ -5065,8 +5065,11 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
5065{5065{
5066 ZigType *enum_type = instruction->target->value->type;5066 ZigType *enum_type = instruction->target->value->type;
5067 assert(enum_type->id == ZigTypeIdEnum);5067 assert(enum_type->id == ZigTypeIdEnum);
5068 if (enum_type->data.enumeration.non_exhaustive)5068 if (enum_type->data.enumeration.non_exhaustive) {
5069 zig_panic("TODO @tagName on non-exhaustive enum");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
5071 LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type);5074 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 *...@@ -8183,13 +8183,6 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
8183 return irb->codegen->invalid_instruction;8183 return irb->codegen->invalid_instruction;
8184 }8184 }
8185 else_prong = prong_node;8185 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 }
8193 } else if (prong_item_count == 1 && 8186 } else if (prong_item_count == 1 &&
8194 prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol &&8187 prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol &&
8195 buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) {8188 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 *...@@ -8201,16 +8194,20 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
8201 return irb->codegen->invalid_instruction;8194 return irb->codegen->invalid_instruction;
8202 }8195 }
8203 underscore_prong = prong_node;8196 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 }
8211 } else {8197 } else {
8212 continue;8198 continue;
8213 }8199 }
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 }
8214 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);8211 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
82158212
8216 IrBasicBlock *prev_block = irb->current_basic_block;8213 IrBasicBlock *prev_block = irb->current_basic_block;
...@@ -22357,8 +22354,11 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns...@@ -22357,8 +22354,11 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
22357 if (instr_is_comptime(target)) {22354 if (instr_is_comptime(target)) {
22358 if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))22355 if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
22359 return ira->codegen->invalid_instruction;22356 return ira->codegen->invalid_instruction;
22360 if (target->value->type->data.enumeration.non_exhaustive)22357 if (target->value->type->data.enumeration.non_exhaustive) {
22361 zig_panic("TODO @tagName on non-exhaustive enum");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 }
22362 TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint);22362 TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint);
22363 ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee;22363 ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee;
22364 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);22364 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);