authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-14 18:06:02-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-14 18:06:57-04:00
logdf4f77024e93dc3b60dd1d76d64e3c5ffa5ebd84
tree59d5026be2d5840255bf48b8d48a94840c26e0cf
parent6536b409df053165ed704148de6ecf5b72e27282
signaturelock-open Commit is signed but in an unrecognized format.

else value when switching on error set has

optional capture value which is subset. see #769

5 files changed, 207 insertions(+), 23 deletions(-)

src/all_types.hpp+8
...@@ -2149,6 +2149,7 @@ enum IrInstructionId {...@@ -2149,6 +2149,7 @@ enum IrInstructionId {
2149 IrInstructionIdCondBr,2149 IrInstructionIdCondBr,
2150 IrInstructionIdSwitchBr,2150 IrInstructionIdSwitchBr,
2151 IrInstructionIdSwitchVar,2151 IrInstructionIdSwitchVar,
2152 IrInstructionIdSwitchElseVar,
2152 IrInstructionIdSwitchTarget,2153 IrInstructionIdSwitchTarget,
2153 IrInstructionIdPhi,2154 IrInstructionIdPhi,
2154 IrInstructionIdUnOp,2155 IrInstructionIdUnOp,
...@@ -2372,6 +2373,13 @@ struct IrInstructionSwitchVar {...@@ -2372,6 +2373,13 @@ struct IrInstructionSwitchVar {
2372 IrInstruction *prong_value;2373 IrInstruction *prong_value;
2373};2374};
23742375
2376struct IrInstructionSwitchElseVar {
2377 IrInstruction base;
2378
2379 IrInstruction *target_value_ptr;
2380 IrInstructionSwitchBr *switch_br;
2381};
2382
2375struct IrInstructionSwitchTarget {2383struct IrInstructionSwitchTarget {
2376 IrInstruction base;2384 IrInstruction base;
23772385
src/codegen.cpp+1
...@@ -5572,6 +5572,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5572,6 +5572,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5572 case IrInstructionIdTypeName:5572 case IrInstructionIdTypeName:
5573 case IrInstructionIdDeclRef:5573 case IrInstructionIdDeclRef:
5574 case IrInstructionIdSwitchVar:5574 case IrInstructionIdSwitchVar:
5575 case IrInstructionIdSwitchElseVar:
5575 case IrInstructionIdByteOffsetOf:5576 case IrInstructionIdByteOffsetOf:
5576 case IrInstructionIdBitOffsetOf:5577 case IrInstructionIdBitOffsetOf:
5577 case IrInstructionIdTypeInfo:5578 case IrInstructionIdTypeInfo:
src/ir.cpp+157-22
...@@ -419,6 +419,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchVar *) {...@@ -419,6 +419,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchVar *) {
419 return IrInstructionIdSwitchVar;419 return IrInstructionIdSwitchVar;
420}420}
421421
422static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchElseVar *) {
423 return IrInstructionIdSwitchElseVar;
424}
425
422static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchTarget *) {426static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchTarget *) {
423 return IrInstructionIdSwitchTarget;427 return IrInstructionIdSwitchTarget;
424}428}
...@@ -1791,7 +1795,7 @@ static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *...@@ -1791,7 +1795,7 @@ static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *
1791 return &instruction->base;1795 return &instruction->base;
1792}1796}
17931797
1794static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value,1798static IrInstructionSwitchBr *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value,
1795 IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime,1799 IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime,
1796 IrInstruction *switch_prongs_void)1800 IrInstruction *switch_prongs_void)
1797{1801{
...@@ -1815,7 +1819,7 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *...@@ -1815,7 +1819,7 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *
1815 ir_ref_bb(cases[i].block);1819 ir_ref_bb(cases[i].block);
1816 }1820 }
18171821
1818 return &instruction->base;1822 return instruction;
1819}1823}
18201824
1821static IrInstruction *ir_build_switch_target(IrBuilder *irb, Scope *scope, AstNode *source_node,1825static IrInstruction *ir_build_switch_target(IrBuilder *irb, Scope *scope, AstNode *source_node,
...@@ -1842,6 +1846,18 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode...@@ -1842,6 +1846,18 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode
1842 return &instruction->base;1846 return &instruction->base;
1843}1847}
18441848
1849// For this instruction the switch_br must be set later.
1850static IrInstructionSwitchElseVar *ir_build_switch_else_var(IrBuilder *irb, Scope *scope, AstNode *source_node,
1851 IrInstruction *target_value_ptr)
1852{
1853 IrInstructionSwitchElseVar *instruction = ir_build_instruction<IrInstructionSwitchElseVar>(irb, scope, source_node);
1854 instruction->target_value_ptr = target_value_ptr;
1855
1856 ir_ref_instruction(target_value_ptr, irb->current_basic_block);
1857
1858 return instruction;
1859}
1860
1845static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1861static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1846 IrInstructionUnionTag *instruction = ir_build_instruction<IrInstructionUnionTag>(irb, scope, source_node);1862 IrInstructionUnionTag *instruction = ir_build_instruction<IrInstructionUnionTag>(irb, scope, source_node);
1847 instruction->value = value;1863 instruction->value = value;
...@@ -6294,7 +6310,8 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6294,7 +6310,8 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6294static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,6310static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
6295 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime,6311 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime,
6296 IrInstruction *target_value_ptr, IrInstruction *prong_value,6312 IrInstruction *target_value_ptr, IrInstruction *prong_value,
6297 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)6313 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values,
6314 IrInstructionSwitchElseVar **out_switch_else_var)
6298{6315{
6299 assert(switch_node->type == NodeTypeSwitchExpr);6316 assert(switch_node->type == NodeTypeSwitchExpr);
6300 assert(prong_node->type == NodeTypeSwitchProng);6317 assert(prong_node->type == NodeTypeSwitchProng);
...@@ -6312,13 +6329,17 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -6312,13 +6329,17 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
6312 ZigVar *var = ir_create_var(irb, var_symbol_node, scope,6329 ZigVar *var = ir_create_var(irb, var_symbol_node, scope,
6313 var_name, is_const, is_const, is_shadowable, var_is_comptime);6330 var_name, is_const, is_const, is_shadowable, var_is_comptime);
6314 child_scope = var->child_scope;6331 child_scope = var->child_scope;
6315 IrInstruction *var_value;6332 IrInstruction *var_ptr_value;
6316 if (prong_value) {6333 if (prong_value != nullptr) {
6317 IrInstruction *var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, prong_value);6334 var_ptr_value = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, prong_value);
6318 var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);
6319 } else {6335 } else {
6320 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);6336 IrInstructionSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node,
6337 target_value_ptr);
6338 *out_switch_else_var = switch_else_var;
6339 var_ptr_value = &switch_else_var->base;
6321 }6340 }
6341 IrInstruction *var_value = var_is_ptr ?
6342 var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);
6322 IrInstruction *var_type = nullptr; // infer the type6343 IrInstruction *var_type = nullptr; // infer the type
6323 ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);6344 ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
6324 } else {6345 } else {
...@@ -6364,6 +6385,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6364,6 +6385,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6364 ZigList<IrBasicBlock *> incoming_blocks = {0};6385 ZigList<IrBasicBlock *> incoming_blocks = {0};
6365 ZigList<IrInstructionCheckSwitchProngsRange> check_ranges = {0};6386 ZigList<IrInstructionCheckSwitchProngsRange> check_ranges = {0};
63666387
6388 IrInstructionSwitchElseVar *switch_else_var = nullptr;
6389
6367 // First do the else and the ranges6390 // First do the else and the ranges
6368 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);6391 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
6369 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);6392 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
...@@ -6384,7 +6407,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6384,7 +6407,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6384 IrBasicBlock *prev_block = irb->current_basic_block;6407 IrBasicBlock *prev_block = irb->current_basic_block;
6385 ir_set_cursor_at_end_and_append_block(irb, else_block);6408 ir_set_cursor_at_end_and_append_block(irb, else_block);
6386 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,6409 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
6387 is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))6410 is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values,
6411 &switch_else_var))
6388 {6412 {
6389 return irb->codegen->invalid_instruction;6413 return irb->codegen->invalid_instruction;
6390 }6414 }
...@@ -6451,7 +6475,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6451,7 +6475,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
64516475
6452 ir_set_cursor_at_end_and_append_block(irb, range_block_yes);6476 ir_set_cursor_at_end_and_append_block(irb, range_block_yes);
6453 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,6477 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
6454 is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))6478 is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values, nullptr))
6455 {6479 {
6456 return irb->codegen->invalid_instruction;6480 return irb->codegen->invalid_instruction;
6457 }6481 }
...@@ -6495,7 +6519,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6495,7 +6519,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6495 IrBasicBlock *prev_block = irb->current_basic_block;6519 IrBasicBlock *prev_block = irb->current_basic_block;
6496 ir_set_cursor_at_end_and_append_block(irb, prong_block);6520 ir_set_cursor_at_end_and_append_block(irb, prong_block);
6497 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,6521 if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
6498 is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))6522 is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values,
6523 nullptr))
6499 {6524 {
6500 return irb->codegen->invalid_instruction;6525 return irb->codegen->invalid_instruction;
6501 }6526 }
...@@ -6510,7 +6535,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6510,7 +6535,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
6510 if (cases.length == 0) {6535 if (cases.length == 0) {
6511 ir_build_br(irb, scope, node, else_block, is_comptime);6536 ir_build_br(irb, scope, node, else_block, is_comptime);
6512 } else {6537 } else {
6513 ir_build_switch_br(irb, scope, node, target_value, else_block, cases.length, cases.items, is_comptime, switch_prongs_void);6538 IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, scope, node, target_value, else_block,
6539 cases.length, cases.items, is_comptime, switch_prongs_void);
6540 if (switch_else_var != nullptr) {
6541 switch_else_var->switch_br = switch_br;
6542 }
6514 }6543 }
65156544
6516 if (!else_prong) {6545 if (!else_prong) {
...@@ -7474,8 +7503,9 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod...@@ -7474,8 +7503,9 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
7474 cases[0].block = resume_block;7503 cases[0].block = resume_block;
7475 cases[1].value = ir_mark_gen(ir_build_const_u8(irb, parent_scope, node, 1));7504 cases[1].value = ir_mark_gen(ir_build_const_u8(irb, parent_scope, node, 1));
7476 cases[1].block = canceled_block;7505 cases[1].block = canceled_block;
7477 ir_mark_gen(ir_build_switch_br(irb, parent_scope, node, suspend_code, irb->exec->coro_suspend_block,7506 IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, parent_scope, node, suspend_code,
7478 2, cases, const_bool_false, nullptr));7507 irb->exec->coro_suspend_block, 2, cases, const_bool_false, nullptr);
7508 ir_mark_gen(&switch_br->base);
74797509
7480 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);7510 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
7481 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);7511 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
...@@ -8972,6 +9002,15 @@ static bool slice_is_const(ZigType *type) {...@@ -8972,6 +9002,15 @@ static bool slice_is_const(ZigType *type) {
8972 return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;9002 return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
8973}9003}
89749004
9005static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) {
9006 assert(set->id == ZigTypeIdErrorSet);
9007 for (uint32_t i = 0; i < set->data.error_set.err_count; i += 1) {
9008 ErrorTableEntry *error_entry = set->data.error_set.errors[i];
9009 assert(errors[error_entry->value] == nullptr);
9010 errors[error_entry->value] = error_entry;
9011 }
9012}
9013
8975static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigType *set2,9014static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigType *set2,
8976 AstNode *source_node)9015 AstNode *source_node)
8977{9016{
...@@ -8991,11 +9030,7 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp...@@ -8991,11 +9030,7 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
8991 return set1;9030 return set1;
8992 }9031 }
8993 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);9032 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
8994 for (uint32_t i = 0; i < set1->data.error_set.err_count; i += 1) {9033 populate_error_set_table(errors, set1);
8995 ErrorTableEntry *error_entry = set1->data.error_set.errors[i];
8996 assert(errors[error_entry->value] == nullptr);
8997 errors[error_entry->value] = error_entry;
8998 }
8999 ZigList<ErrorTableEntry *> intersection_list = {};9034 ZigList<ErrorTableEntry *> intersection_list = {};
90009035
9001 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);9036 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
...@@ -10410,6 +10445,24 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -10410,6 +10445,24 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
10410 return ir_exec_const_result(codegen, analyzed_executable);10445 return ir_exec_const_result(codegen, analyzed_executable);
10411}10446}
1041210447
10448static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_value) {
10449 if (type_is_invalid(err_value->value.type))
10450 return nullptr;
10451
10452 if (err_value->value.type->id != ZigTypeIdErrorSet) {
10453 ir_add_error(ira, err_value,
10454 buf_sprintf("expected error, found '%s'", buf_ptr(&err_value->value.type->name)));
10455 return nullptr;
10456 }
10457
10458 ConstExprValue *const_val = ir_resolve_const(ira, err_value, UndefBad);
10459 if (!const_val)
10460 return nullptr;
10461
10462 assert(const_val->data.x_err_set != nullptr);
10463 return const_val->data.x_err_set;
10464}
10465
10413static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {10466static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
10414 if (type_is_invalid(type_value->value.type))10467 if (type_is_invalid(type_value->value.type))
10415 return ira->codegen->builtin_types.entry_invalid;10468 return ira->codegen->builtin_types.entry_invalid;
...@@ -17229,11 +17282,11 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira,...@@ -17229,11 +17282,11 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira,
17229 }17282 }
1723017283
17231 IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block, &switch_br_instruction->base);17284 IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block, &switch_br_instruction->base);
17232 IrInstruction *result = ir_build_switch_br(&ira->new_irb,17285 IrInstructionSwitchBr *switch_br = ir_build_switch_br(&ira->new_irb,
17233 switch_br_instruction->base.scope, switch_br_instruction->base.source_node,17286 switch_br_instruction->base.scope, switch_br_instruction->base.source_node,
17234 target_value, new_else_block, case_count, cases, nullptr, nullptr);17287 target_value, new_else_block, case_count, cases, nullptr, nullptr);
17235 result->value.type = ira->codegen->builtin_types.entry_unreachable;17288 switch_br->base.value.type = ira->codegen->builtin_types.entry_unreachable;
17236 return ir_finish_anal(ira, result);17289 return ir_finish_anal(ira, &switch_br->base);
17237}17290}
1723817291
17239static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,17292static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
...@@ -17419,6 +17472,85 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru...@@ -17419,6 +17472,85 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
17419 }17472 }
17420}17473}
1742117474
17475static IrInstruction *ir_analyze_instruction_switch_else_var(IrAnalyze *ira,
17476 IrInstructionSwitchElseVar *instruction)
17477{
17478 IrInstruction *target_value_ptr = instruction->target_value_ptr->child;
17479 if (type_is_invalid(target_value_ptr->value.type))
17480 return ira->codegen->invalid_instruction;
17481
17482 ZigType *ref_type = target_value_ptr->value.type;
17483 assert(ref_type->id == ZigTypeIdPointer);
17484 ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
17485 if (target_type->id == ZigTypeIdErrorSet) {
17486 // make a new set that has the other cases removed
17487 if (!resolve_inferred_error_set(ira->codegen, target_type, instruction->base.source_node)) {
17488 return ira->codegen->invalid_instruction;
17489 }
17490 if (type_is_global_error_set(target_type)) {
17491 // the type of the else capture variable still has to be the global error set.
17492 // once the runtime hint system is more sophisticated, we could add some hint information here.
17493 return target_value_ptr;
17494 }
17495 // Make note of the errors handled by other cases
17496 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
17497 for (size_t case_i = 0; case_i < instruction->switch_br->case_count; case_i += 1) {
17498 IrInstructionSwitchBrCase *br_case = &instruction->switch_br->cases[case_i];
17499 IrInstruction *case_expr = br_case->value->child;
17500 if (case_expr->value.type->id == ZigTypeIdErrorSet) {
17501 ErrorTableEntry *err = ir_resolve_error(ira, case_expr);
17502 if (err == nullptr)
17503 return ira->codegen->invalid_instruction;
17504 errors[err->value] = err;
17505 } else if (case_expr->value.type->id == ZigTypeIdMetaType) {
17506 ZigType *err_set_type = ir_resolve_type(ira, case_expr);
17507 if (type_is_invalid(err_set_type))
17508 return ira->codegen->invalid_instruction;
17509 populate_error_set_table(errors, err_set_type);
17510 } else {
17511 zig_unreachable();
17512 }
17513 }
17514 ZigList<ErrorTableEntry *> result_list = {};
17515
17516 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
17517 buf_resize(&err_set_type->name, 0);
17518 buf_appendf(&err_set_type->name, "error{");
17519
17520 // Look at all the errors in the type switched on and add them to the result_list
17521 // if they are not handled by cases.
17522 for (uint32_t i = 0; i < target_type->data.error_set.err_count; i += 1) {
17523 ErrorTableEntry *error_entry = target_type->data.error_set.errors[i];
17524 ErrorTableEntry *existing_entry = errors[error_entry->value];
17525 if (existing_entry == nullptr) {
17526 result_list.append(error_entry);
17527 buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name));
17528 }
17529 }
17530 free(errors);
17531
17532 err_set_type->data.error_set.err_count = result_list.length;
17533 err_set_type->data.error_set.errors = result_list.items;
17534 err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
17535 err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
17536 err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
17537
17538 buf_appendf(&err_set_type->name, "}");
17539
17540 ZigType *new_target_value_ptr_type = get_pointer_to_type_extra(ira->codegen,
17541 err_set_type,
17542 ref_type->data.pointer.is_const, ref_type->data.pointer.is_volatile,
17543 ref_type->data.pointer.ptr_len,
17544 ref_type->data.pointer.explicit_alignment,
17545 ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,
17546 ref_type->data.pointer.allow_zero);
17547 return ir_analyze_ptr_cast(ira, &instruction->base, target_value_ptr, new_target_value_ptr_type,
17548 &instruction->base, false);
17549 }
17550
17551 return target_value_ptr;
17552}
17553
17422static IrInstruction *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) {17554static IrInstruction *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) {
17423 IrInstruction *value = instruction->value->child;17555 IrInstruction *value = instruction->value->child;
17424 return ir_analyze_union_tag(ira, &instruction->base, value);17556 return ir_analyze_union_tag(ira, &instruction->base, value);
...@@ -23094,6 +23226,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -23094,6 +23226,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
23094 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);23226 return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction);
23095 case IrInstructionIdSwitchVar:23227 case IrInstructionIdSwitchVar:
23096 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);23228 return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction);
23229 case IrInstructionIdSwitchElseVar:
23230 return ir_analyze_instruction_switch_else_var(ira, (IrInstructionSwitchElseVar *)instruction);
23097 case IrInstructionIdUnionTag:23231 case IrInstructionIdUnionTag:
23098 return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction);23232 return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction);
23099 case IrInstructionIdImport:23233 case IrInstructionIdImport:
...@@ -23457,6 +23591,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -23457,6 +23591,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
23457 case IrInstructionIdCtz:23591 case IrInstructionIdCtz:
23458 case IrInstructionIdPopCount:23592 case IrInstructionIdPopCount:
23459 case IrInstructionIdSwitchVar:23593 case IrInstructionIdSwitchVar:
23594 case IrInstructionIdSwitchElseVar:
23460 case IrInstructionIdSwitchTarget:23595 case IrInstructionIdSwitchTarget:
23461 case IrInstructionIdUnionTag:23596 case IrInstructionIdUnionTag:
23462 case IrInstructionIdRef:23597 case IrInstructionIdRef:
src/ir_print.cpp+8
...@@ -546,6 +546,11 @@ static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instructio...@@ -546,6 +546,11 @@ static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instructio
546 ir_print_other_instruction(irp, instruction->prong_value);546 ir_print_other_instruction(irp, instruction->prong_value);
547}547}
548548
549static void ir_print_switch_else_var(IrPrint *irp, IrInstructionSwitchElseVar *instruction) {
550 fprintf(irp->f, "switchelsevar ");
551 ir_print_other_instruction(irp, &instruction->switch_br->base);
552}
553
549static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *instruction) {554static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *instruction) {
550 fprintf(irp->f, "switchtarget ");555 fprintf(irp->f, "switchtarget ");
551 ir_print_other_instruction(irp, instruction->target_value_ptr);556 ir_print_other_instruction(irp, instruction->target_value_ptr);
...@@ -1559,6 +1564,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1559,6 +1564,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1559 case IrInstructionIdSwitchVar:1564 case IrInstructionIdSwitchVar:
1560 ir_print_switch_var(irp, (IrInstructionSwitchVar *)instruction);1565 ir_print_switch_var(irp, (IrInstructionSwitchVar *)instruction);
1561 break;1566 break;
1567 case IrInstructionIdSwitchElseVar:
1568 ir_print_switch_else_var(irp, (IrInstructionSwitchElseVar *)instruction);
1569 break;
1562 case IrInstructionIdSwitchTarget:1570 case IrInstructionIdSwitchTarget:
1563 ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);1571 ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction);
1564 break;1572 break;
test/stage1/behavior/switch.zig+33-1
...@@ -1,4 +1,6 @@...@@ -1,4 +1,6 @@
1const expect = @import("std").testing.expect;1const std = @import("std");
2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
24
3test "switch with numbers" {5test "switch with numbers" {
4 testSwitchWithNumbers(13);6 testSwitchWithNumbers(13);
...@@ -296,3 +298,33 @@ test "anon enum literal used in switch on union enum" {...@@ -296,3 +298,33 @@ test "anon enum literal used in switch on union enum" {
296 },298 },
297 }299 }
298}300}
301
302test "else prong of switch on error set excludes other cases" {
303 const S = struct {
304 fn doTheTest() void {
305 expectError(error.C, bar());
306 }
307 const E = error{
308 A,
309 B,
310 } || E2;
311
312 const E2 = error{
313 C,
314 D,
315 };
316
317 fn foo() E!void {
318 return error.C;
319 }
320
321 fn bar() E2!void {
322 foo() catch |err| switch (err) {
323 error.A, error.B => {},
324 else => |e| return e,
325 };
326 }
327 };
328 S.doTheTest();
329 comptime S.doTheTest();
330}