authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-02 11:59:34-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-04-02 11:59:34-07:00
logfc9c1b4e4ae86c36a7ff29859cc589a9816ab7d5
treec5472fe8e6a291831de78e0914741bf724d82b5a
parentf270bef9a4d21e880826cef6b5264acdc84f0a6f
parent2d286100ef7ae87a71af1ace0002398d405e33d2
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #8028 from mguaypaq/nosuspend-allow

stage1: allow async and resume inside nosuspend blocks

3 files changed, 64 insertions(+), 13 deletions(-)

src/stage1/ir.cpp+1-10
...@@ -7641,12 +7641,7 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,...@@ -7641,12 +7641,7 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,
76417641
7642 bool is_nosuspend = get_scope_nosuspend(scope) != nullptr;7642 bool is_nosuspend = get_scope_nosuspend(scope) != nullptr;
7643 CallModifier modifier = node->data.fn_call_expr.modifier;7643 CallModifier modifier = node->data.fn_call_expr.modifier;
7644 if (is_nosuspend) {7644 if (is_nosuspend && modifier != CallModifierAsync) {
7645 if (modifier == CallModifierAsync) {
7646 add_node_error(irb->codegen, node,
7647 buf_sprintf("async call in nosuspend scope"));
7648 return irb->codegen->invalid_inst_src;
7649 }
7650 modifier = CallModifierNoSuspend;7645 modifier = CallModifierNoSuspend;
7651 }7646 }
76527647
...@@ -10129,10 +10124,6 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod...@@ -10129,10 +10124,6 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
1012910124
10130static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) {10125static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
10131 assert(node->type == NodeTypeResume);10126 assert(node->type == NodeTypeResume);
10132 if (get_scope_nosuspend(scope) != nullptr) {
10133 add_node_error(irb->codegen, node, buf_sprintf("resume in nosuspend scope"));
10134 return irb->codegen->invalid_inst_src;
10135 }
1013610127
10137 IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr);10128 IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr);
10138 if (target_inst == irb->codegen->invalid_inst_src)10129 if (target_inst == irb->codegen->invalid_inst_src)
test/compile_errors.zig-2
...@@ -1027,9 +1027,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1027,9 +1027,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1027 \\}1027 \\}
1028 \\fn foo() void {}1028 \\fn foo() void {}
1029 , &[_][]const u8{1029 , &[_][]const u8{
1030 "tmp.zig:3:21: error: async call in nosuspend scope",
1031 "tmp.zig:4:9: error: suspend in nosuspend scope",1030 "tmp.zig:4:9: error: suspend in nosuspend scope",
1032 "tmp.zig:5:9: error: resume in nosuspend scope",
1033 });1031 });
10341032
1035 cases.add("atomicrmw with bool op not .Xchg",1033 cases.add("atomicrmw with bool op not .Xchg",
test/stage1/behavior/async_fn.zig+63-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = std.builtin;
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
5const expectEqualStrings = std.testing.expectEqualStrings;5const expectEqualStrings = std.testing.expectEqualStrings;
...@@ -1545,6 +1545,68 @@ test "nosuspend on function calls" {...@@ -1545,6 +1545,68 @@ test "nosuspend on function calls" {
1545 expectEqual(@as(i32, 42), (try nosuspend S1.d()).b);1545 expectEqual(@as(i32, 42), (try nosuspend S1.d()).b);
1546}1546}
15471547
1548test "nosuspend on async function calls" {
1549 const S0 = struct {
1550 b: i32 = 42,
1551 };
1552 const S1 = struct {
1553 fn c() S0 {
1554 return S0{};
1555 }
1556 fn d() !S0 {
1557 return S0{};
1558 }
1559 };
1560 var frame_c = nosuspend async S1.c();
1561 expectEqual(@as(i32, 42), (await frame_c).b);
1562 var frame_d = nosuspend async S1.d();
1563 expectEqual(@as(i32, 42), (try await frame_d).b);
1564}
1565
1566// test "resume nosuspend async function calls" {
1567// const S0 = struct {
1568// b: i32 = 42,
1569// };
1570// const S1 = struct {
1571// fn c() S0 {
1572// suspend;
1573// return S0{};
1574// }
1575// fn d() !S0 {
1576// suspend;
1577// return S0{};
1578// }
1579// };
1580// var frame_c = nosuspend async S1.c();
1581// resume frame_c;
1582// expectEqual(@as(i32, 42), (await frame_c).b);
1583// var frame_d = nosuspend async S1.d();
1584// resume frame_d;
1585// expectEqual(@as(i32, 42), (try await frame_d).b);
1586// }
1587
1588test "nosuspend resume async function calls" {
1589 const S0 = struct {
1590 b: i32 = 42,
1591 };
1592 const S1 = struct {
1593 fn c() S0 {
1594 suspend;
1595 return S0{};
1596 }
1597 fn d() !S0 {
1598 suspend;
1599 return S0{};
1600 }
1601 };
1602 var frame_c = async S1.c();
1603 nosuspend resume frame_c;
1604 expectEqual(@as(i32, 42), (await frame_c).b);
1605 var frame_d = async S1.d();
1606 nosuspend resume frame_d;
1607 expectEqual(@as(i32, 42), (try await frame_d).b);
1608}
1609
1548test "avoid forcing frame alignment resolution implicit cast to *c_void" {1610test "avoid forcing frame alignment resolution implicit cast to *c_void" {
1549 const S = struct {1611 const S = struct {
1550 var x: ?*c_void = null;1612 var x: ?*c_void = null;