| author | |
| committer | |
| log | 18af2f9a2764cc340571578d58cb2575faeccdc6 |
| tree | 547d4c68ab6a6c062ce10bef556e9c92272e5a6e |
| parent | b1c07c0ea9e351a43c9bc2fe747fc07c0a19e005 |
closes #8567 files changed, 89 insertions(+), 14 deletions(-)
src/all_types.hpp+11-1| ... | @@ -1251,7 +1251,10 @@ struct FnTableEntry { | ... | @@ -1251,7 +1251,10 @@ struct FnTableEntry { |
| 1251 | ScopeBlock *def_scope; // parent is child_scope | 1251 | ScopeBlock *def_scope; // parent is child_scope |
| 1252 | Buf symbol_name; | 1252 | Buf symbol_name; |
| 1253 | TypeTableEntry *type_entry; // function type | 1253 | TypeTableEntry *type_entry; // function type |
| 1254 | TypeTableEntry *implicit_return_type; | 1254 | // in the case of normal functions this is the implicit return type |
| 1255 | // in the case of async functions this is the implicit return type according to the | ||
| 1256 | // zig source code, not according to zig ir | ||
| 1257 | TypeTableEntry *src_implicit_return_type; | ||
| 1255 | bool is_test; | 1258 | bool is_test; |
| 1256 | FnInline fn_inline; | 1259 | FnInline fn_inline; |
| 1257 | FnAnalState anal_state; | 1260 | FnAnalState anal_state; |
| ... | @@ -2035,6 +2038,7 @@ enum IrInstructionId { | ... | @@ -2035,6 +2038,7 @@ enum IrInstructionId { |
| 2035 | IrInstructionIdPromiseResultType, | 2038 | IrInstructionIdPromiseResultType, |
| 2036 | IrInstructionIdAwaitBookkeeping, | 2039 | IrInstructionIdAwaitBookkeeping, |
| 2037 | IrInstructionIdSaveErrRetAddr, | 2040 | IrInstructionIdSaveErrRetAddr, |
| 2041 | IrInstructionIdAddImplicitReturnType, | ||
| 2038 | }; | 2042 | }; |
| 2039 | 2043 | ||
| 2040 | struct IrInstruction { | 2044 | struct IrInstruction { |
| ... | @@ -2993,6 +2997,12 @@ struct IrInstructionSaveErrRetAddr { | ... | @@ -2993,6 +2997,12 @@ struct IrInstructionSaveErrRetAddr { |
| 2993 | IrInstruction base; | 2997 | IrInstruction base; |
| 2994 | }; | 2998 | }; |
| 2995 | 2999 | ||
| 3000 | struct IrInstructionAddImplicitReturnType { | ||
| 3001 | IrInstruction base; | ||
| 3002 | |||
| 3003 | IrInstruction *value; | ||
| 3004 | }; | ||
| 3005 | |||
| 2996 | static const size_t slice_ptr_index = 0; | 3006 | static const size_t slice_ptr_index = 0; |
| 2997 | static const size_t slice_len_index = 1; | 3007 | static const size_t slice_len_index = 1; |
| 2998 | 3008 |
src/analyze.cpp+5-5| ... | @@ -3865,7 +3865,7 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ | ... | @@ -3865,7 +3865,7 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ |
| 3865 | 3865 | ||
| 3866 | TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable, | 3866 | TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable, |
| 3867 | &fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node); | 3867 | &fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node); |
| 3868 | fn_table_entry->implicit_return_type = block_return_type; | 3868 | fn_table_entry->src_implicit_return_type = block_return_type; |
| 3869 | 3869 | ||
| 3870 | if (type_is_invalid(block_return_type) || fn_table_entry->analyzed_executable.invalid) { | 3870 | if (type_is_invalid(block_return_type) || fn_table_entry->analyzed_executable.invalid) { |
| 3871 | assert(g->errors.length > 0); | 3871 | assert(g->errors.length > 0); |
| ... | @@ -3877,10 +3877,10 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ | ... | @@ -3877,10 +3877,10 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ |
| 3877 | TypeTableEntry *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type; | 3877 | TypeTableEntry *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type; |
| 3878 | if (return_err_set_type->data.error_set.infer_fn != nullptr) { | 3878 | if (return_err_set_type->data.error_set.infer_fn != nullptr) { |
| 3879 | TypeTableEntry *inferred_err_set_type; | 3879 | TypeTableEntry *inferred_err_set_type; |
| 3880 | if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorSet) { | 3880 | if (fn_table_entry->src_implicit_return_type->id == TypeTableEntryIdErrorSet) { |
| 3881 | inferred_err_set_type = fn_table_entry->implicit_return_type; | 3881 | inferred_err_set_type = fn_table_entry->src_implicit_return_type; |
| 3882 | } else if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorUnion) { | 3882 | } else if (fn_table_entry->src_implicit_return_type->id == TypeTableEntryIdErrorUnion) { |
| 3883 | inferred_err_set_type = fn_table_entry->implicit_return_type->data.error_union.err_set_type; | 3883 | inferred_err_set_type = fn_table_entry->src_implicit_return_type->data.error_union.err_set_type; |
| 3884 | } else { | 3884 | } else { |
| 3885 | add_node_error(g, return_type_node, | 3885 | add_node_error(g, return_type_node, |
| 3886 | buf_sprintf("function with inferred error set must return at least one possible error")); | 3886 | buf_sprintf("function with inferred error set must return at least one possible error")); |
src/ast_render.cpp+10-1| ... | @@ -658,6 +658,15 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -658,6 +658,15 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 658 | if (node->data.fn_call_expr.is_builtin) { | 658 | if (node->data.fn_call_expr.is_builtin) { |
| 659 | fprintf(ar->f, "@"); | 659 | fprintf(ar->f, "@"); |
| 660 | } | 660 | } |
| 661 | if (node->data.fn_call_expr.is_async) { | ||
| 662 | fprintf(ar->f, "async"); | ||
| 663 | if (node->data.fn_call_expr.async_allocator != nullptr) { | ||
| 664 | fprintf(ar->f, "<"); | ||
| 665 | render_node_extra(ar, node->data.fn_call_expr.async_allocator, true); | ||
| 666 | fprintf(ar->f, ">"); | ||
| 667 | } | ||
| 668 | fprintf(ar->f, " "); | ||
| 669 | } | ||
| 661 | AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; | 670 | AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; |
| 662 | bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypeAddrOfExpr); | 671 | bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypeAddrOfExpr); |
| 663 | render_node_extra(ar, fn_ref_node, grouped); | 672 | render_node_extra(ar, fn_ref_node, grouped); |
| ... | @@ -1023,7 +1032,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -1023,7 +1032,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 1023 | case NodeTypeUnwrapErrorExpr: | 1032 | case NodeTypeUnwrapErrorExpr: |
| 1024 | { | 1033 | { |
| 1025 | render_node_ungrouped(ar, node->data.unwrap_err_expr.op1); | 1034 | render_node_ungrouped(ar, node->data.unwrap_err_expr.op1); |
| 1026 | fprintf(ar->f, " %%%% "); | 1035 | fprintf(ar->f, " catch "); |
| 1027 | if (node->data.unwrap_err_expr.symbol) { | 1036 | if (node->data.unwrap_err_expr.symbol) { |
| 1028 | Buf *var_name = node->data.unwrap_err_expr.symbol->data.symbol_expr.symbol; | 1037 | Buf *var_name = node->data.unwrap_err_expr.symbol->data.symbol_expr.symbol; |
| 1029 | fprintf(ar->f, "|%s| ", buf_ptr(var_name)); | 1038 | fprintf(ar->f, "|%s| ", buf_ptr(var_name)); |
src/codegen.cpp+1| ... | @@ -4245,6 +4245,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -4245,6 +4245,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 4245 | case IrInstructionIdErrorUnion: | 4245 | case IrInstructionIdErrorUnion: |
| 4246 | case IrInstructionIdPromiseResultType: | 4246 | case IrInstructionIdPromiseResultType: |
| 4247 | case IrInstructionIdAwaitBookkeeping: | 4247 | case IrInstructionIdAwaitBookkeeping: |
| 4248 | case IrInstructionIdAddImplicitReturnType: | ||
| 4248 | zig_unreachable(); | 4249 | zig_unreachable(); |
| 4249 | 4250 | ||
| 4250 | case IrInstructionIdReturn: | 4251 | case IrInstructionIdReturn: |
src/ir.cpp+40-5| ... | @@ -34,7 +34,7 @@ struct IrAnalyze { | ... | @@ -34,7 +34,7 @@ struct IrAnalyze { |
| 34 | size_t old_bb_index; | 34 | size_t old_bb_index; |
| 35 | size_t instruction_index; | 35 | size_t instruction_index; |
| 36 | TypeTableEntry *explicit_return_type; | 36 | TypeTableEntry *explicit_return_type; |
| 37 | ZigList<IrInstruction *> implicit_return_type_list; | 37 | ZigList<IrInstruction *> src_implicit_return_type_list; |
| 38 | IrBasicBlock *const_predecessor_bb; | 38 | IrBasicBlock *const_predecessor_bb; |
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| ... | @@ -717,6 +717,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr * | ... | @@ -717,6 +717,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr * |
| 717 | return IrInstructionIdSaveErrRetAddr; | 717 | return IrInstructionIdSaveErrRetAddr; |
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAddImplicitReturnType *) { | ||
| 721 | return IrInstructionIdAddImplicitReturnType; | ||
| 722 | } | ||
| 723 | |||
| 720 | template<typename T> | 724 | template<typename T> |
| 721 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 725 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 722 | T *special_instruction = allocate<T>(1); | 726 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2687,6 +2691,17 @@ static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, A | ... | @@ -2687,6 +2691,17 @@ static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, A |
| 2687 | return &instruction->base; | 2691 | return &instruction->base; |
| 2688 | } | 2692 | } |
| 2689 | 2693 | ||
| 2694 | static IrInstruction *ir_build_add_implicit_return_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2695 | IrInstruction *value) | ||
| 2696 | { | ||
| 2697 | IrInstructionAddImplicitReturnType *instruction = ir_build_instruction<IrInstructionAddImplicitReturnType>(irb, scope, source_node); | ||
| 2698 | instruction->value = value; | ||
| 2699 | |||
| 2700 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 2701 | |||
| 2702 | return &instruction->base; | ||
| 2703 | } | ||
| 2704 | |||
| 2690 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2705 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2691 | results[ReturnKindUnconditional] = 0; | 2706 | results[ReturnKindUnconditional] = 0; |
| 2692 | results[ReturnKindError] = 0; | 2707 | results[ReturnKindError] = 0; |
| ... | @@ -2767,6 +2782,8 @@ static bool exec_is_async(IrExecutable *exec) { | ... | @@ -2767,6 +2782,8 @@ static bool exec_is_async(IrExecutable *exec) { |
| 2767 | static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value, | 2782 | static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value, |
| 2768 | bool is_generated_code) | 2783 | bool is_generated_code) |
| 2769 | { | 2784 | { |
| 2785 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value)); | ||
| 2786 | |||
| 2770 | bool is_async = exec_is_async(irb->exec); | 2787 | bool is_async = exec_is_async(irb->exec); |
| 2771 | if (!is_async) { | 2788 | if (!is_async) { |
| 2772 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); | 2789 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); |
| ... | @@ -6399,6 +6416,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -6399,6 +6416,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6399 | ir_build_cond_br(irb, scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false); | 6416 | ir_build_cond_br(irb, scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false); |
| 6400 | 6417 | ||
| 6401 | ir_set_cursor_at_end_and_append_block(irb, alloc_err_block); | 6418 | ir_set_cursor_at_end_and_append_block(irb, alloc_err_block); |
| 6419 | // we can return undefined here, because the caller passes a pointer to the error struct field | ||
| 6420 | // in the error union result, and we populate it in case of allocation failure. | ||
| 6402 | IrInstruction *undef = ir_build_const_undefined(irb, scope, node); | 6421 | IrInstruction *undef = ir_build_const_undefined(irb, scope, node); |
| 6403 | ir_build_return(irb, scope, node, undef); | 6422 | ir_build_return(irb, scope, node, undef); |
| 6404 | 6423 | ||
| ... | @@ -10108,13 +10127,26 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { | ... | @@ -10108,13 +10127,26 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 10108 | return result; | 10127 | return result; |
| 10109 | } | 10128 | } |
| 10110 | 10129 | ||
| 10130 | static TypeTableEntry *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira, | ||
| 10131 | IrInstructionAddImplicitReturnType *instruction) | ||
| 10132 | { | ||
| 10133 | IrInstruction *value = instruction->value->other; | ||
| 10134 | if (type_is_invalid(value->value.type)) | ||
| 10135 | return ir_unreach_error(ira); | ||
| 10136 | |||
| 10137 | ira->src_implicit_return_type_list.append(value); | ||
| 10138 | |||
| 10139 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 10140 | out_val->type = ira->codegen->builtin_types.entry_void; | ||
| 10141 | return out_val->type; | ||
| 10142 | } | ||
| 10143 | |||
| 10111 | static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, | 10144 | static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, |
| 10112 | IrInstructionReturn *return_instruction) | 10145 | IrInstructionReturn *return_instruction) |
| 10113 | { | 10146 | { |
| 10114 | IrInstruction *value = return_instruction->value->other; | 10147 | IrInstruction *value = return_instruction->value->other; |
| 10115 | if (type_is_invalid(value->value.type)) | 10148 | if (type_is_invalid(value->value.type)) |
| 10116 | return ir_unreach_error(ira); | 10149 | return ir_unreach_error(ira); |
| 10117 | ira->implicit_return_type_list.append(value); | ||
| 10118 | 10150 | ||
| 10119 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type); | 10151 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type); |
| 10120 | if (casted_value == ira->codegen->invalid_instruction) | 10152 | if (casted_value == ira->codegen->invalid_instruction) |
| ... | @@ -18049,6 +18081,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -18049,6 +18081,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 18049 | return ir_analyze_instruction_await_bookkeeping(ira, (IrInstructionAwaitBookkeeping *)instruction); | 18081 | return ir_analyze_instruction_await_bookkeeping(ira, (IrInstructionAwaitBookkeeping *)instruction); |
| 18050 | case IrInstructionIdSaveErrRetAddr: | 18082 | case IrInstructionIdSaveErrRetAddr: |
| 18051 | return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction); | 18083 | return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction); |
| 18084 | case IrInstructionIdAddImplicitReturnType: | ||
| 18085 | return ir_analyze_instruction_add_implicit_return_type(ira, (IrInstructionAddImplicitReturnType *)instruction); | ||
| 18052 | } | 18086 | } |
| 18053 | zig_unreachable(); | 18087 | zig_unreachable(); |
| 18054 | } | 18088 | } |
| ... | @@ -18122,11 +18156,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl | ... | @@ -18122,11 +18156,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 18122 | 18156 | ||
| 18123 | if (new_exec->invalid) { | 18157 | if (new_exec->invalid) { |
| 18124 | return ira->codegen->builtin_types.entry_invalid; | 18158 | return ira->codegen->builtin_types.entry_invalid; |
| 18125 | } else if (ira->implicit_return_type_list.length == 0) { | 18159 | } else if (ira->src_implicit_return_type_list.length == 0) { |
| 18126 | return codegen->builtin_types.entry_unreachable; | 18160 | return codegen->builtin_types.entry_unreachable; |
| 18127 | } else { | 18161 | } else { |
| 18128 | return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items, | 18162 | return ir_resolve_peer_types(ira, expected_type_source_node, ira->src_implicit_return_type_list.items, |
| 18129 | ira->implicit_return_type_list.length); | 18163 | ira->src_implicit_return_type_list.length); |
| 18130 | } | 18164 | } |
| 18131 | } | 18165 | } |
| 18132 | 18166 | ||
| ... | @@ -18175,6 +18209,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -18175,6 +18209,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 18175 | case IrInstructionIdCoroAllocHelper: | 18209 | case IrInstructionIdCoroAllocHelper: |
| 18176 | case IrInstructionIdAwaitBookkeeping: | 18210 | case IrInstructionIdAwaitBookkeeping: |
| 18177 | case IrInstructionIdSaveErrRetAddr: | 18211 | case IrInstructionIdSaveErrRetAddr: |
| 18212 | case IrInstructionIdAddImplicitReturnType: | ||
| 18178 | return true; | 18213 | return true; |
| 18179 | 18214 | ||
| 18180 | case IrInstructionIdPhi: | 18215 | case IrInstructionIdPhi: |
src/ir_print.cpp+11-2| ... | @@ -201,9 +201,9 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) { | ... | @@ -201,9 +201,9 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) { |
| 201 | if (call_instruction->is_async) { | 201 | if (call_instruction->is_async) { |
| 202 | fprintf(irp->f, "async"); | 202 | fprintf(irp->f, "async"); |
| 203 | if (call_instruction->async_allocator != nullptr) { | 203 | if (call_instruction->async_allocator != nullptr) { |
| 204 | fprintf(irp->f, "("); | 204 | fprintf(irp->f, "<"); |
| 205 | ir_print_other_instruction(irp, call_instruction->async_allocator); | 205 | ir_print_other_instruction(irp, call_instruction->async_allocator); |
| 206 | fprintf(irp->f, ")"); | 206 | fprintf(irp->f, ">"); |
| 207 | } | 207 | } |
| 208 | fprintf(irp->f, " "); | 208 | fprintf(irp->f, " "); |
| 209 | } | 209 | } |
| ... | @@ -1165,6 +1165,12 @@ static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr | ... | @@ -1165,6 +1165,12 @@ static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr |
| 1165 | fprintf(irp->f, "@saveErrRetAddr()"); | 1165 | fprintf(irp->f, "@saveErrRetAddr()"); |
| 1166 | } | 1166 | } |
| 1167 | 1167 | ||
| 1168 | static void ir_print_add_implicit_return_type(IrPrint *irp, IrInstructionAddImplicitReturnType *instruction) { | ||
| 1169 | fprintf(irp->f, "@addImplicitReturnType("); | ||
| 1170 | ir_print_other_instruction(irp, instruction->value); | ||
| 1171 | fprintf(irp->f, ")"); | ||
| 1172 | } | ||
| 1173 | |||
| 1168 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1174 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1169 | ir_print_prefix(irp, instruction); | 1175 | ir_print_prefix(irp, instruction); |
| 1170 | switch (instruction->id) { | 1176 | switch (instruction->id) { |
| ... | @@ -1539,6 +1545,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1539,6 +1545,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1539 | case IrInstructionIdSaveErrRetAddr: | 1545 | case IrInstructionIdSaveErrRetAddr: |
| 1540 | ir_print_save_err_ret_addr(irp, (IrInstructionSaveErrRetAddr *)instruction); | 1546 | ir_print_save_err_ret_addr(irp, (IrInstructionSaveErrRetAddr *)instruction); |
| 1541 | break; | 1547 | break; |
| 1548 | case IrInstructionIdAddImplicitReturnType: | ||
| 1549 | ir_print_add_implicit_return_type(irp, (IrInstructionAddImplicitReturnType *)instruction); | ||
| 1550 | break; | ||
| 1542 | } | 1551 | } |
| 1543 | fprintf(irp->f, "\n"); | 1552 | fprintf(irp->f, "\n"); |
| 1544 | } | 1553 | } |
test/cases/coroutines.zig+11| ... | @@ -176,3 +176,14 @@ async<&std.mem.Allocator> fn simpleAsyncFn2(y: &i32) void { | ... | @@ -176,3 +176,14 @@ async<&std.mem.Allocator> fn simpleAsyncFn2(y: &i32) void { |
| 176 | *y += 1; | 176 | *y += 1; |
| 177 | suspend; | 177 | suspend; |
| 178 | } | 178 | } |
| 179 | |||
| 180 | test "async fn with inferred error set" { | ||
| 181 | const p = (async<std.debug.global_allocator> failing()) catch unreachable; | ||
| 182 | resume p; | ||
| 183 | cancel p; | ||
| 184 | } | ||
| 185 | |||
| 186 | async fn failing() !void { | ||
| 187 | suspend; | ||
| 188 | return error.Fail; | ||
| 189 | } |