authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-17 17:22:20-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-17 17:22:20-04:00
log57b90d2d98154e382c58f1b385de2bcef132f7d9
treef2f5e504f39ca670ff5860a56be7145c8db1c024
parent66a490c27c01c958d8d20dbc289c6b2b934a724e
signaturelock-open Commit is signed but in an unrecognized format.

allow implicit cast of fn to async fn

it forces the fn to be async. closes #3079

2 files changed, 51 insertions(+), 5 deletions(-)

src/ir.cpp+24-5
...@@ -9485,10 +9485,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9485,10 +9485,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9485 result.id = ConstCastResultIdFnAlign;9485 result.id = ConstCastResultIdFnAlign;
9486 return result;9486 return result;
9487 }9487 }
9488 if (wanted_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
9489 result.id = ConstCastResultIdFnCC;
9490 return result;
9491 }
9492 if (wanted_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {9488 if (wanted_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
9493 result.id = ConstCastResultIdFnVarArgs;9489 result.id = ConstCastResultIdFnVarArgs;
9494 return result;9490 return result;
...@@ -9546,6 +9542,11 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9546,6 +9542,11 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9546 return result;9542 return result;
9547 }9543 }
9548 }9544 }
9545 if (wanted_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
9546 // ConstCastResultIdFnCC is guaranteed to be the last one reported, meaning everything else is ok.
9547 result.id = ConstCastResultIdFnCC;
9548 return result;
9549 }
9549 return result;9550 return result;
9550 }9551 }
95519552
...@@ -11780,8 +11781,11 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -11780,8 +11781,11 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
11780 add_error_note(ira->codegen, parent_msg, source_node,11781 add_error_note(ira->codegen, parent_msg, source_node,
11781 buf_sprintf("only one of the functions is generic"));11782 buf_sprintf("only one of the functions is generic"));
11782 break;11783 break;
11784 case ConstCastResultIdFnCC:
11785 add_error_note(ira->codegen, parent_msg, source_node,
11786 buf_sprintf("calling convention mismatch"));
11787 break;
11783 case ConstCastResultIdFnAlign: // TODO11788 case ConstCastResultIdFnAlign: // TODO
11784 case ConstCastResultIdFnCC: // TODO
11785 case ConstCastResultIdFnVarArgs: // TODO11789 case ConstCastResultIdFnVarArgs: // TODO
11786 case ConstCastResultIdFnReturnType: // TODO11790 case ConstCastResultIdFnReturnType: // TODO
11787 case ConstCastResultIdFnArgCount: // TODO11791 case ConstCastResultIdFnArgCount: // TODO
...@@ -11891,6 +11895,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11891,6 +11895,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11891 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);11895 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);
11892 }11896 }
1189311897
11898 if (const_cast_result.id == ConstCastResultIdFnCC) {
11899 ir_assert(value->value.type->id == ZigTypeIdFn, source_instr);
11900 // ConstCastResultIdFnCC is guaranteed to be the last one reported, meaning everything else is ok.
11901 if (wanted_type->data.fn.fn_type_id.cc == CallingConventionAsync &&
11902 actual_type->data.fn.fn_type_id.cc == CallingConventionUnspecified)
11903 {
11904 ir_assert(value->value.data.x_ptr.special == ConstPtrSpecialFunction, source_instr);
11905 ZigFn *fn = value->value.data.x_ptr.data.fn.fn_entry;
11906 if (fn->inferred_async_node == nullptr) {
11907 fn->inferred_async_node = source_instr->source_node;
11908 }
11909 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);
11910 }
11911 }
11912
11894 // cast from T to ?T11913 // cast from T to ?T
11895 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism11914 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
11896 if (wanted_type->id == ZigTypeIdOptional) {11915 if (wanted_type->id == ZigTypeIdOptional) {
test/stage1/behavior/async_fn.zig+27
...@@ -817,3 +817,30 @@ test "struct parameter to async function is copied to the frame" {...@@ -817,3 +817,30 @@ test "struct parameter to async function is copied to the frame" {
817 };817 };
818 S.doTheTest();818 S.doTheTest();
819}819}
820
821test "cast fn to async fn when it is inferred to be async" {
822 const S = struct {
823 var frame: anyframe = undefined;
824 var ok = false;
825
826 fn doTheTest() void {
827 var ptr: async fn () i32 = undefined;
828 ptr = func;
829 var buf: [100]u8 align(16) = undefined;
830 var result: i32 = undefined;
831 _ = await @asyncCall(&buf, &result, ptr);
832 expect(result == 1234);
833 ok = true;
834 }
835
836 fn func() i32 {
837 suspend {
838 frame = @frame();
839 }
840 return 1234;
841 }
842 };
843 _ = async S.doTheTest();
844 resume S.frame;
845 expect(S.ok);
846}