Commit 57b90d2d98
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -9485,10 +9485,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
result.id = ConstCastResultIdFnAlign;
return result;
}
- if (wanted_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
- result.id = ConstCastResultIdFnCC;
- return result;
- }
if (wanted_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
result.id = ConstCastResultIdFnVarArgs;
return result;
@@ -9546,6 +9542,11 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
return result;
}
}
+ if (wanted_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
+ // ConstCastResultIdFnCC is guaranteed to be the last one reported, meaning everything else is ok.
+ result.id = ConstCastResultIdFnCC;
+ return result;
+ }
return result;
}
@@ -11780,8 +11781,11 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
add_error_note(ira->codegen, parent_msg, source_node,
buf_sprintf("only one of the functions is generic"));
break;
+ case ConstCastResultIdFnCC:
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("calling convention mismatch"));
+ break;
case ConstCastResultIdFnAlign: // TODO
- case ConstCastResultIdFnCC: // TODO
case ConstCastResultIdFnVarArgs: // TODO
case ConstCastResultIdFnReturnType: // TODO
case ConstCastResultIdFnArgCount: // TODO
@@ -11891,6 +11895,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);
}
+ if (const_cast_result.id == ConstCastResultIdFnCC) {
+ ir_assert(value->value.type->id == ZigTypeIdFn, source_instr);
+ // ConstCastResultIdFnCC is guaranteed to be the last one reported, meaning everything else is ok.
+ if (wanted_type->data.fn.fn_type_id.cc == CallingConventionAsync &&
+ actual_type->data.fn.fn_type_id.cc == CallingConventionUnspecified)
+ {
+ ir_assert(value->value.data.x_ptr.special == ConstPtrSpecialFunction, source_instr);
+ ZigFn *fn = value->value.data.x_ptr.data.fn.fn_entry;
+ if (fn->inferred_async_node == nullptr) {
+ fn->inferred_async_node = source_instr->source_node;
+ }
+ return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop);
+ }
+ }
+
// cast from T to ?T
// note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
if (wanted_type->id == ZigTypeIdOptional) {
test/stage1/behavior/async_fn.zig
@@ -817,3 +817,30 @@ test "struct parameter to async function is copied to the frame" {
};
S.doTheTest();
}
+
+test "cast fn to async fn when it is inferred to be async" {
+ const S = struct {
+ var frame: anyframe = undefined;
+ var ok = false;
+
+ fn doTheTest() void {
+ var ptr: async fn () i32 = undefined;
+ ptr = func;
+ var buf: [100]u8 align(16) = undefined;
+ var result: i32 = undefined;
+ _ = await @asyncCall(&buf, &result, ptr);
+ expect(result == 1234);
+ ok = true;
+ }
+
+ fn func() i32 {
+ suspend {
+ frame = @frame();
+ }
+ return 1234;
+ }
+ };
+ _ = async S.doTheTest();
+ resume S.frame;
+ expect(S.ok);
+}