authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-24 13:34:33-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-04-24 13:34:33-04:00
log29e5e98eed2161c37edbce41b96c2999eb1f3177
treeaf80f2749253cc4f5c61c14c9f37519dc9146ab8
parent4ec6d174adc038741f1274d157f5253752eb8d51
parenteabf378a56e0cd9720f43c36b85025228c4406d8
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #8606 from LemonBoy/suspend-block

stage1: Require a block after suspend

10 files changed, 122 insertions(+), 91 deletions(-)

doc/langref.html.in+5-5
...@@ -6528,7 +6528,7 @@ test "suspend with no resume" {...@@ -6528,7 +6528,7 @@ test "suspend with no resume" {
65286528
6529fn func() void {6529fn func() void {
6530 x += 1;6530 x += 1;
6531 suspend;6531 suspend {}
6532 // This line is never reached because the suspend has no matching resume.6532 // This line is never reached because the suspend has no matching resume.
6533 x += 1;6533 x += 1;
6534}6534}
...@@ -6593,7 +6593,7 @@ fn testResumeFromSuspend(my_result: *i32) void {...@@ -6593,7 +6593,7 @@ fn testResumeFromSuspend(my_result: *i32) void {
6593 resume @frame();6593 resume @frame();
6594 }6594 }
6595 my_result.* += 1;6595 my_result.* += 1;
6596 suspend;6596 suspend {}
6597 my_result.* += 1;6597 my_result.* += 1;
6598}6598}
6599 {#code_end#}6599 {#code_end#}
...@@ -6632,7 +6632,7 @@ fn amain() void {...@@ -6632,7 +6632,7 @@ fn amain() void {
6632}6632}
66336633
6634fn func() void {6634fn func() void {
6635 suspend;6635 suspend {}
6636}6636}
6637 {#code_end#}6637 {#code_end#}
6638 <p>6638 <p>
...@@ -6934,7 +6934,7 @@ test "async fn pointer in a struct field" {...@@ -6934,7 +6934,7 @@ test "async fn pointer in a struct field" {
6934fn func(y: *i32) void {6934fn func(y: *i32) void {
6935 defer y.* += 2;6935 defer y.* += 2;
6936 y.* += 1;6936 y.* += 1;
6937 suspend;6937 suspend {}
6938}6938}
6939 {#code_end#}6939 {#code_end#}
6940 {#header_close#}6940 {#header_close#}
...@@ -7667,7 +7667,7 @@ test "heap allocated frame" {...@@ -7667,7 +7667,7 @@ test "heap allocated frame" {
7667}7667}
76687668
7669fn func() void {7669fn func() void {
7670 suspend;7670 suspend {}
7671}7671}
7672 {#code_end#}7672 {#code_end#}
7673 {#header_close#}7673 {#header_close#}
lib/std/event/rwlock.zig+2-2
...@@ -264,7 +264,7 @@ var shared_test_data = [1]i32{0} ** 10;...@@ -264,7 +264,7 @@ var shared_test_data = [1]i32{0} ** 10;
264var shared_test_index: usize = 0;264var shared_test_index: usize = 0;
265var shared_count: usize = 0;265var shared_count: usize = 0;
266fn writeRunner(lock: *RwLock) callconv(.Async) void {266fn writeRunner(lock: *RwLock) callconv(.Async) void {
267 suspend; // resumed by onNextTick267 suspend {} // resumed by onNextTick
268268
269 var i: usize = 0;269 var i: usize = 0;
270 while (i < shared_test_data.len) : (i += 1) {270 while (i < shared_test_data.len) : (i += 1) {
...@@ -281,7 +281,7 @@ fn writeRunner(lock: *RwLock) callconv(.Async) void {...@@ -281,7 +281,7 @@ fn writeRunner(lock: *RwLock) callconv(.Async) void {
281 }281 }
282}282}
283fn readRunner(lock: *RwLock) callconv(.Async) void {283fn readRunner(lock: *RwLock) callconv(.Async) void {
284 suspend; // resumed by onNextTick284 suspend {} // resumed by onNextTick
285 std.time.sleep(1);285 std.time.sleep(1);
286286
287 var i: usize = 0;287 var i: usize = 0;
lib/std/zig/parse.zig+2-1
...@@ -852,7 +852,7 @@ const Parser = struct {...@@ -852,7 +852,7 @@ const Parser = struct {
852 /// <- KEYWORD_comptime? VarDecl852 /// <- KEYWORD_comptime? VarDecl
853 /// / KEYWORD_comptime BlockExprStatement853 /// / KEYWORD_comptime BlockExprStatement
854 /// / KEYWORD_nosuspend BlockExprStatement854 /// / KEYWORD_nosuspend BlockExprStatement
855 /// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)855 /// / KEYWORD_suspend BlockExprStatement
856 /// / KEYWORD_defer BlockExprStatement856 /// / KEYWORD_defer BlockExprStatement
857 /// / KEYWORD_errdefer Payload? BlockExprStatement857 /// / KEYWORD_errdefer Payload? BlockExprStatement
858 /// / IfStatement858 /// / IfStatement
...@@ -892,6 +892,7 @@ const Parser = struct {...@@ -892,6 +892,7 @@ const Parser = struct {
892 },892 },
893 .keyword_suspend => {893 .keyword_suspend => {
894 const token = p.nextToken();894 const token = p.nextToken();
895 // TODO remove this special case when 0.9.0 is released.
895 const block_expr: Node.Index = if (p.eatToken(.semicolon) != null)896 const block_expr: Node.Index = if (p.eatToken(.semicolon) != null)
896 0897 0
897 else898 else
lib/std/zig/parser_test.zig+33-3
...@@ -40,6 +40,21 @@ test "zig fmt: rewrite inline functions as callconv(.Inline)" {...@@ -40,6 +40,21 @@ test "zig fmt: rewrite inline functions as callconv(.Inline)" {
40 );40 );
41}41}
4242
43// TODO Remove this after zig 0.9.0 is released.
44test "zig fmt: rewrite suspend without block expression" {
45 try testTransform(
46 \\fn foo() void {
47 \\ suspend;
48 \\}
49 \\
50 ,
51 \\fn foo() void {
52 \\ suspend {}
53 \\}
54 \\
55 );
56}
57
43test "zig fmt: simple top level comptime block" {58test "zig fmt: simple top level comptime block" {
44 try testCanonical(59 try testCanonical(
45 \\// line comment60 \\// line comment
...@@ -3665,9 +3680,9 @@ test "zig fmt: async functions" {...@@ -3665,9 +3680,9 @@ test "zig fmt: async functions" {
3665 \\fn simpleAsyncFn() void {3680 \\fn simpleAsyncFn() void {
3666 \\ const a = async a.b();3681 \\ const a = async a.b();
3667 \\ x += 1;3682 \\ x += 1;
3668 \\ suspend;3683 \\ suspend {}
3669 \\ x += 1;3684 \\ x += 1;
3670 \\ suspend;3685 \\ suspend {}
3671 \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;3686 \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
3672 \\ await p;3687 \\ await p;
3673 \\}3688 \\}
...@@ -5022,6 +5037,21 @@ test "recovery: invalid comptime" {...@@ -5022,6 +5037,21 @@ test "recovery: invalid comptime" {
5022 });5037 });
5023}5038}
50245039
5040test "recovery: missing block after suspend" {
5041 // TODO Enable this after zig 0.9.0 is released.
5042 if (true) return error.SkipZigTest;
5043
5044 try testError(
5045 \\fn foo() void {
5046 \\ suspend;
5047 \\ nosuspend;
5048 \\}
5049 , &[_]Error{
5050 .expected_block_or_expr,
5051 .expected_block_or_expr,
5052 });
5053}
5054
5025test "recovery: missing block after for/while loops" {5055test "recovery: missing block after for/while loops" {
5026 try testError(5056 try testError(
5027 \\test "" { while (foo) }5057 \\test "" { while (foo) }
...@@ -5165,7 +5195,7 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {...@@ -5165,7 +5195,7 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {
5165 var tree = try std.zig.parse(std.testing.allocator, source);5195 var tree = try std.zig.parse(std.testing.allocator, source);
5166 defer tree.deinit(std.testing.allocator);5196 defer tree.deinit(std.testing.allocator);
51675197
5168 std.testing.expect(tree.errors.len == expected_errors.len);5198 std.testing.expectEqual(expected_errors.len, tree.errors.len);
5169 for (expected_errors) |expected, i| {5199 for (expected_errors) |expected, i| {
5170 std.testing.expectEqual(expected, tree.errors[i].tag);5200 std.testing.expectEqual(expected, tree.errors[i].tag);
5171 }5201 }
lib/std/zig/render.zig+6-1
...@@ -269,7 +269,12 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I...@@ -269,7 +269,12 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I
269 try renderToken(ais, tree, suspend_token, .space);269 try renderToken(ais, tree, suspend_token, .space);
270 return renderExpression(gpa, ais, tree, body, space);270 return renderExpression(gpa, ais, tree, body, space);
271 } else {271 } else {
272 return renderToken(ais, tree, suspend_token, space);272 // TODO remove this special case when 0.9.0 is released.
273 assert(space == .semicolon);
274 try renderToken(ais, tree, suspend_token, .space);
275 try ais.writer().writeAll("{}");
276 try ais.insertNewline();
277 return;
273 }278 }
274 },279 },
275280
src/stage1/ir.cpp+7-9
...@@ -9534,7 +9534,7 @@ static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNo...@@ -9534,7 +9534,7 @@ static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNo
95349534
9535 Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope);9535 Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope);
9536 // purposefully pass null for result_loc and let EndExpr handle it9536 // purposefully pass null for result_loc and let EndExpr handle it
9537 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);9537 return ir_gen_node_extra(irb, node->data.nosuspend_expr.expr, child_scope, lval, nullptr);
9538}9538}
95399539
9540static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {9540static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
...@@ -10199,14 +10199,12 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode...@@ -10199,14 +10199,12 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode
10199 }10199 }
1020010200
10201 IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node);10201 IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node);
10202 if (node->data.suspend.block != nullptr) {10202 ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);
10203 ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);10203 Scope *child_scope = &suspend_scope->base;
10204 Scope *child_scope = &suspend_scope->base;10204 IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);
10205 IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);10205 if (susp_res == irb->codegen->invalid_inst_src)
10206 if (susp_res == irb->codegen->invalid_inst_src)10206 return irb->codegen->invalid_inst_src;
10207 return irb->codegen->invalid_inst_src;10207 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
10208 ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
10209 }
1021010208
10211 return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin));10209 return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin));
10212}10210}
src/stage1/parser.cpp+1-4
...@@ -946,10 +946,7 @@ static AstNode *ast_parse_statement(ParseContext *pc) {...@@ -946,10 +946,7 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
946946
947 Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);947 Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);
948 if (suspend != nullptr) {948 if (suspend != nullptr) {
949 AstNode *statement = nullptr;949 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
950 if (eat_token_if(pc, TokenIdSemicolon) == nullptr)
951 statement = ast_expect(pc, ast_parse_block_expr_statement);
952
953 AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend);950 AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend);
954 res->data.suspend.block = statement;951 res->data.suspend.block = statement;
955 return res;952 return res;
test/compile_errors.zig+7-7
...@@ -1021,7 +1021,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1021,7 +1021,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1021 \\export fn entry() void {1021 \\export fn entry() void {
1022 \\ nosuspend {1022 \\ nosuspend {
1023 \\ const bar = async foo();1023 \\ const bar = async foo();
1024 \\ suspend;1024 \\ suspend {}
1025 \\ resume bar;1025 \\ resume bar;
1026 \\ }1026 \\ }
1027 \\}1027 \\}
...@@ -2120,7 +2120,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2120,7 +2120,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2120 \\ non_async_fn = func;2120 \\ non_async_fn = func;
2121 \\}2121 \\}
2122 \\fn func() void {2122 \\fn func() void {
2123 \\ suspend;2123 \\ suspend {}
2124 \\}2124 \\}
2125 , &[_][]const u8{2125 , &[_][]const u8{
2126 "tmp.zig:5:1: error: 'func' cannot be async",2126 "tmp.zig:5:1: error: 'func' cannot be async",
...@@ -2198,7 +2198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2198,7 +2198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2198 \\ var x: anyframe = &f;2198 \\ var x: anyframe = &f;
2199 \\}2199 \\}
2200 \\fn func() void {2200 \\fn func() void {
2201 \\ suspend;2201 \\ suspend {}
2202 \\}2202 \\}
2203 , &[_][]const u8{2203 , &[_][]const u8{
2204 "tmp.zig:3:12: error: expected type 'anyframe', found '*const @Frame(func)'",2204 "tmp.zig:3:12: error: expected type 'anyframe', found '*const @Frame(func)'",
...@@ -2231,10 +2231,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2231,10 +2231,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2231 \\ frame = async bar();2231 \\ frame = async bar();
2232 \\}2232 \\}
2233 \\fn foo() void {2233 \\fn foo() void {
2234 \\ suspend;2234 \\ suspend {}
2235 \\}2235 \\}
2236 \\fn bar() void {2236 \\fn bar() void {
2237 \\ suspend;2237 \\ suspend {}
2238 \\}2238 \\}
2239 , &[_][]const u8{2239 , &[_][]const u8{
2240 "tmp.zig:3:13: error: expected type '*@Frame(bar)', found '*@Frame(foo)'",2240 "tmp.zig:3:13: error: expected type '*@Frame(bar)', found '*@Frame(foo)'",
...@@ -2269,7 +2269,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2269,7 +2269,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2269 \\ var result = await frame;2269 \\ var result = await frame;
2270 \\}2270 \\}
2271 \\fn func() void {2271 \\fn func() void {
2272 \\ suspend;2272 \\ suspend {}
2273 \\}2273 \\}
2274 , &[_][]const u8{2274 , &[_][]const u8{
2275 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",2275 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
...@@ -2347,7 +2347,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2347,7 +2347,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2347 \\ bar();2347 \\ bar();
2348 \\}2348 \\}
2349 \\fn bar() void {2349 \\fn bar() void {
2350 \\ suspend;2350 \\ suspend {}
2351 \\}2351 \\}
2352 , &[_][]const u8{2352 , &[_][]const u8{
2353 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",2353 "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
test/runtime_safety.zig+17-17
...@@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
1313
14 cases.addRuntimeSafety("switch on corrupted enum value",14 cases.addRuntimeSafety("switch on corrupted enum value",
15 \\const std = @import("std");15 \\const std = @import("std");
16 ++ check_panic_msg ++16 ++ check_panic_msg ++
17 \\const E = enum(u32) {17 \\const E = enum(u32) {
18 \\ X = 1,18 \\ X = 1,
19 \\};19 \\};
...@@ -28,7 +28,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -28,7 +28,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
2828
29 cases.addRuntimeSafety("switch on corrupted union value",29 cases.addRuntimeSafety("switch on corrupted union value",
30 \\const std = @import("std");30 \\const std = @import("std");
31 ++ check_panic_msg ++31 ++ check_panic_msg ++
32 \\const U = union(enum(u32)) {32 \\const U = union(enum(u32)) {
33 \\ X: u8,33 \\ X: u8,
34 \\};34 \\};
...@@ -54,7 +54,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -54,7 +54,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
5454
55 cases.addRuntimeSafety("@tagName on corrupted enum value",55 cases.addRuntimeSafety("@tagName on corrupted enum value",
56 \\const std = @import("std");56 \\const std = @import("std");
57 ++ check_panic_msg ++57 ++ check_panic_msg ++
58 \\const E = enum(u32) {58 \\const E = enum(u32) {
59 \\ X = 1,59 \\ X = 1,
60 \\};60 \\};
...@@ -67,7 +67,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -67,7 +67,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
6767
68 cases.addRuntimeSafety("@tagName on corrupted union value",68 cases.addRuntimeSafety("@tagName on corrupted union value",
69 \\const std = @import("std");69 \\const std = @import("std");
70 ++ check_panic_msg ++70 ++ check_panic_msg ++
71 \\const U = union(enum(u32)) {71 \\const U = union(enum(u32)) {
72 \\ X: u8,72 \\ X: u8,
73 \\};73 \\};
...@@ -92,7 +92,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -92,7 +92,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
9292
93 cases.addRuntimeSafety("slicing operator with sentinel",93 cases.addRuntimeSafety("slicing operator with sentinel",
94 \\const std = @import("std");94 \\const std = @import("std");
95 ++ check_panic_msg ++95 ++ check_panic_msg ++
96 \\pub fn main() void {96 \\pub fn main() void {
97 \\ var buf = [4]u8{'a','b','c',0};97 \\ var buf = [4]u8{'a','b','c',0};
98 \\ const slice = buf[0..4 :0];98 \\ const slice = buf[0..4 :0];
...@@ -100,7 +100,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -100,7 +100,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
100 );100 );
101 cases.addRuntimeSafety("slicing operator with sentinel",101 cases.addRuntimeSafety("slicing operator with sentinel",
102 \\const std = @import("std");102 \\const std = @import("std");
103 ++ check_panic_msg ++103 ++ check_panic_msg ++
104 \\pub fn main() void {104 \\pub fn main() void {
105 \\ var buf = [4]u8{'a','b','c',0};105 \\ var buf = [4]u8{'a','b','c',0};
106 \\ const slice = buf[0..:0];106 \\ const slice = buf[0..:0];
...@@ -108,7 +108,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -108,7 +108,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
108 );108 );
109 cases.addRuntimeSafety("slicing operator with sentinel",109 cases.addRuntimeSafety("slicing operator with sentinel",
110 \\const std = @import("std");110 \\const std = @import("std");
111 ++ check_panic_msg ++111 ++ check_panic_msg ++
112 \\pub fn main() void {112 \\pub fn main() void {
113 \\ var buf_zero = [0]u8{};113 \\ var buf_zero = [0]u8{};
114 \\ const slice = buf_zero[0..0 :0];114 \\ const slice = buf_zero[0..0 :0];
...@@ -116,7 +116,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -116,7 +116,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
116 );116 );
117 cases.addRuntimeSafety("slicing operator with sentinel",117 cases.addRuntimeSafety("slicing operator with sentinel",
118 \\const std = @import("std");118 \\const std = @import("std");
119 ++ check_panic_msg ++119 ++ check_panic_msg ++
120 \\pub fn main() void {120 \\pub fn main() void {
121 \\ var buf_zero = [0]u8{};121 \\ var buf_zero = [0]u8{};
122 \\ const slice = buf_zero[0..:0];122 \\ const slice = buf_zero[0..:0];
...@@ -124,7 +124,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -124,7 +124,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
124 );124 );
125 cases.addRuntimeSafety("slicing operator with sentinel",125 cases.addRuntimeSafety("slicing operator with sentinel",
126 \\const std = @import("std");126 \\const std = @import("std");
127 ++ check_panic_msg ++127 ++ check_panic_msg ++
128 \\pub fn main() void {128 \\pub fn main() void {
129 \\ var buf_sentinel = [2:0]u8{'a','b'};129 \\ var buf_sentinel = [2:0]u8{'a','b'};
130 \\ @ptrCast(*[3]u8, &buf_sentinel)[2] = 0;130 \\ @ptrCast(*[3]u8, &buf_sentinel)[2] = 0;
...@@ -133,7 +133,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -133,7 +133,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
133 );133 );
134 cases.addRuntimeSafety("slicing operator with sentinel",134 cases.addRuntimeSafety("slicing operator with sentinel",
135 \\const std = @import("std");135 \\const std = @import("std");
136 ++ check_panic_msg ++136 ++ check_panic_msg ++
137 \\pub fn main() void {137 \\pub fn main() void {
138 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };138 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };
139 \\ const slice = buf_slice[0..3 :0];139 \\ const slice = buf_slice[0..3 :0];
...@@ -141,7 +141,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -141,7 +141,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
141 );141 );
142 cases.addRuntimeSafety("slicing operator with sentinel",142 cases.addRuntimeSafety("slicing operator with sentinel",
143 \\const std = @import("std");143 \\const std = @import("std");
144 ++ check_panic_msg ++144 ++ check_panic_msg ++
145 \\pub fn main() void {145 \\pub fn main() void {
146 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };146 \\ var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };
147 \\ const slice = buf_slice[0.. :0];147 \\ const slice = buf_slice[0.. :0];
...@@ -367,7 +367,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -367,7 +367,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
367 \\}367 \\}
368 \\fn add(a: i32, b: i32) i32 {368 \\fn add(a: i32, b: i32) i32 {
369 \\ if (a > 100) {369 \\ if (a > 100) {
370 \\ suspend;370 \\ suspend {}
371 \\ }371 \\ }
372 \\ return a + b;372 \\ return a + b;
373 \\}373 \\}
...@@ -407,7 +407,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -407,7 +407,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
407 \\ var frame = @asyncCall(&bytes, {}, ptr, .{});407 \\ var frame = @asyncCall(&bytes, {}, ptr, .{});
408 \\}408 \\}
409 \\fn other() callconv(.Async) void {409 \\fn other() callconv(.Async) void {
410 \\ suspend;410 \\ suspend {}
411 \\}411 \\}
412 );412 );
413413
...@@ -424,7 +424,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -424,7 +424,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
424 \\ await frame;424 \\ await frame;
425 \\}425 \\}
426 \\fn other() void {426 \\fn other() void {
427 \\ suspend;427 \\ suspend {}
428 \\}428 \\}
429 );429 );
430430
...@@ -440,7 +440,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -440,7 +440,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
440 \\ other();440 \\ other();
441 \\}441 \\}
442 \\fn other() void {442 \\fn other() void {
443 \\ suspend;443 \\ suspend {}
444 \\}444 \\}
445 );445 );
446446
...@@ -454,7 +454,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -454,7 +454,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
454 \\ resume p; //bad454 \\ resume p; //bad
455 \\}455 \\}
456 \\fn suspendOnce() void {456 \\fn suspendOnce() void {
457 \\ suspend;457 \\ suspend {}
458 \\}458 \\}
459 );459 );
460460
...@@ -1019,7 +1019,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -1019,7 +1019,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
1019 \\}1019 \\}
1020 \\1020 \\
1021 \\fn failing() anyerror!void {1021 \\fn failing() anyerror!void {
1022 \\ suspend;1022 \\ suspend {}
1023 \\ return second();1023 \\ return second();
1024 \\}1024 \\}
1025 \\1025 \\
test/stage1/behavior/async_fn.zig+42-42
...@@ -18,9 +18,9 @@ test "simple coroutine suspend and resume" {...@@ -18,9 +18,9 @@ test "simple coroutine suspend and resume" {
18}18}
19fn simpleAsyncFn() void {19fn simpleAsyncFn() void {
20 global_x += 1;20 global_x += 1;
21 suspend;21 suspend {}
22 global_x += 1;22 global_x += 1;
23 suspend;23 suspend {}
24 global_x += 1;24 global_x += 1;
25}25}
2626
...@@ -34,7 +34,7 @@ test "pass parameter to coroutine" {...@@ -34,7 +34,7 @@ test "pass parameter to coroutine" {
34}34}
35fn simpleAsyncFnWithArg(delta: i32) void {35fn simpleAsyncFnWithArg(delta: i32) void {
36 global_y += delta;36 global_y += delta;
37 suspend;37 suspend {}
38 global_y += delta;38 global_y += delta;
39}39}
4040
...@@ -50,7 +50,7 @@ test "suspend at end of function" {...@@ -50,7 +50,7 @@ test "suspend at end of function" {
5050
51 fn suspendAtEnd() void {51 fn suspendAtEnd() void {
52 x += 1;52 x += 1;
53 suspend;53 suspend {}
54 }54 }
55 };55 };
56 S.doTheTest();56 S.doTheTest();
...@@ -74,11 +74,11 @@ test "local variable in async function" {...@@ -74,11 +74,11 @@ test "local variable in async function" {
7474
75 fn add(a: i32, b: i32) void {75 fn add(a: i32, b: i32) void {
76 var accum: i32 = 0;76 var accum: i32 = 0;
77 suspend;77 suspend {}
78 accum += a;78 accum += a;
79 suspend;79 suspend {}
80 accum += b;80 accum += b;
81 suspend;81 suspend {}
82 x = accum;82 x = accum;
83 }83 }
84 };84 };
...@@ -102,7 +102,7 @@ test "calling an inferred async function" {...@@ -102,7 +102,7 @@ test "calling an inferred async function" {
102 }102 }
103 fn other() void {103 fn other() void {
104 other_frame = @frame();104 other_frame = @frame();
105 suspend;105 suspend {}
106 x += 1;106 x += 1;
107 }107 }
108 };108 };
...@@ -129,7 +129,7 @@ test "@frameSize" {...@@ -129,7 +129,7 @@ test "@frameSize" {
129 }129 }
130 fn other(param: i32) void {130 fn other(param: i32) void {
131 var local: i32 = undefined;131 var local: i32 = undefined;
132 suspend;132 suspend {}
133 }133 }
134 };134 };
135 S.doTheTest();135 S.doTheTest();
...@@ -269,7 +269,7 @@ test "async function with dot syntax" {...@@ -269,7 +269,7 @@ test "async function with dot syntax" {
269 var y: i32 = 1;269 var y: i32 = 1;
270 fn foo() callconv(.Async) void {270 fn foo() callconv(.Async) void {
271 y += 1;271 y += 1;
272 suspend;272 suspend {}
273 }273 }
274 };274 };
275 const p = async S.foo();275 const p = async S.foo();
...@@ -298,7 +298,7 @@ fn doTheAwait(f: anyframe->void) void {...@@ -298,7 +298,7 @@ fn doTheAwait(f: anyframe->void) void {
298fn simpleAsyncFn2(y: *i32) callconv(.Async) void {298fn simpleAsyncFn2(y: *i32) callconv(.Async) void {
299 defer y.* += 2;299 defer y.* += 2;
300 y.* += 1;300 y.* += 1;
301 suspend;301 suspend {}
302}302}
303303
304test "@asyncCall with return type" {304test "@asyncCall with return type" {
...@@ -312,7 +312,7 @@ test "@asyncCall with return type" {...@@ -312,7 +312,7 @@ test "@asyncCall with return type" {
312312
313 fn afunc() i32 {313 fn afunc() i32 {
314 global_frame = @frame();314 global_frame = @frame();
315 suspend;315 suspend {}
316 return 1234;316 return 1234;
317 }317 }
318 };318 };
...@@ -348,7 +348,7 @@ test "async fn with inferred error set" {...@@ -348,7 +348,7 @@ test "async fn with inferred error set" {
348348
349 fn failing() !void {349 fn failing() !void {
350 global_frame = @frame();350 global_frame = @frame();
351 suspend;351 suspend {}
352 return error.Fail;352 return error.Fail;
353 }353 }
354 };354 };
...@@ -375,7 +375,7 @@ fn nonFailing() (anyframe->anyerror!void) {...@@ -375,7 +375,7 @@ fn nonFailing() (anyframe->anyerror!void) {
375 return &Static.frame;375 return &Static.frame;
376}376}
377fn suspendThenFail() callconv(.Async) anyerror!void {377fn suspendThenFail() callconv(.Async) anyerror!void {
378 suspend;378 suspend {}
379 return error.Fail;379 return error.Fail;
380}380}
381fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void {381fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void {
...@@ -400,7 +400,7 @@ fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void {...@@ -400,7 +400,7 @@ fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void {
400 resume @frame();400 resume @frame();
401 }401 }
402 my_result.* += 1;402 my_result.* += 1;
403 suspend;403 suspend {}
404 my_result.* += 1;404 my_result.* += 1;
405}405}
406406
...@@ -421,7 +421,7 @@ test "heap allocated async function frame" {...@@ -421,7 +421,7 @@ test "heap allocated async function frame" {
421421
422 fn someFunc() void {422 fn someFunc() void {
423 x += 1;423 x += 1;
424 suspend;424 suspend {}
425 x += 1;425 x += 1;
426 }426 }
427 };427 };
...@@ -454,7 +454,7 @@ test "async function call return value" {...@@ -454,7 +454,7 @@ test "async function call return value" {
454454
455 fn other(x: i32, y: i32) Point {455 fn other(x: i32, y: i32) Point {
456 frame = @frame();456 frame = @frame();
457 suspend;457 suspend {}
458 return Point{458 return Point{
459 .x = x,459 .x = x,
460 .y = y,460 .y = y,
...@@ -487,7 +487,7 @@ test "suspension points inside branching control flow" {...@@ -487,7 +487,7 @@ test "suspension points inside branching control flow" {
487487
488 fn func(b: bool) void {488 fn func(b: bool) void {
489 while (b) {489 while (b) {
490 suspend;490 suspend {}
491 result += 1;491 result += 1;
492 }492 }
493 }493 }
...@@ -541,7 +541,7 @@ test "pass string literal to async function" {...@@ -541,7 +541,7 @@ test "pass string literal to async function" {
541541
542 fn hello(msg: []const u8) void {542 fn hello(msg: []const u8) void {
543 frame = @frame();543 frame = @frame();
544 suspend;544 suspend {}
545 expectEqualStrings("hello", msg);545 expectEqualStrings("hello", msg);
546 ok = true;546 ok = true;
547 }547 }
...@@ -566,7 +566,7 @@ test "await inside an errdefer" {...@@ -566,7 +566,7 @@ test "await inside an errdefer" {
566566
567 fn func() void {567 fn func() void {
568 frame = @frame();568 frame = @frame();
569 suspend;569 suspend {}
570 }570 }
571 };571 };
572 S.doTheTest();572 S.doTheTest();
...@@ -590,7 +590,7 @@ test "try in an async function with error union and non-zero-bit payload" {...@@ -590,7 +590,7 @@ test "try in an async function with error union and non-zero-bit payload" {
590590
591 fn theProblem() ![]u8 {591 fn theProblem() ![]u8 {
592 frame = @frame();592 frame = @frame();
593 suspend;593 suspend {}
594 const result = try other();594 const result = try other();
595 return result;595 return result;
596 }596 }
...@@ -622,7 +622,7 @@ test "returning a const error from async function" {...@@ -622,7 +622,7 @@ test "returning a const error from async function" {
622622
623 fn fetchUrl(unused: i32, url: []const u8) ![]u8 {623 fn fetchUrl(unused: i32, url: []const u8) ![]u8 {
624 frame = @frame();624 frame = @frame();
625 suspend;625 suspend {}
626 ok = true;626 ok = true;
627 return error.OutOfMemory;627 return error.OutOfMemory;
628 }628 }
...@@ -967,7 +967,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {...@@ -967,7 +967,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
967967
968 fn failing() !void {968 fn failing() !void {
969 global_frame = @frame();969 global_frame = @frame();
970 suspend;970 suspend {}
971 return error.Fail;971 return error.Fail;
972 }972 }
973 };973 };
...@@ -977,7 +977,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {...@@ -977,7 +977,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
977test "@asyncCall with actual frame instead of byte buffer" {977test "@asyncCall with actual frame instead of byte buffer" {
978 const S = struct {978 const S = struct {
979 fn func() i32 {979 fn func() i32 {
980 suspend;980 suspend {}
981 return 1234;981 return 1234;
982 }982 }
983 };983 };
...@@ -993,7 +993,7 @@ test "@asyncCall using the result location inside the frame" {...@@ -993,7 +993,7 @@ test "@asyncCall using the result location inside the frame" {
993 fn simple2(y: *i32) callconv(.Async) i32 {993 fn simple2(y: *i32) callconv(.Async) i32 {
994 defer y.* += 2;994 defer y.* += 2;
995 y.* += 1;995 y.* += 1;
996 suspend;996 suspend {}
997 return 1234;997 return 1234;
998 }998 }
999 fn getAnswer(f: anyframe->i32, out: *i32) void {999 fn getAnswer(f: anyframe->i32, out: *i32) void {
...@@ -1095,7 +1095,7 @@ test "nosuspend function call" {...@@ -1095,7 +1095,7 @@ test "nosuspend function call" {
1095 }1095 }
1096 fn add(a: i32, b: i32) i32 {1096 fn add(a: i32, b: i32) i32 {
1097 if (a > 100) {1097 if (a > 100) {
1098 suspend;1098 suspend {}
1099 }1099 }
1100 return a + b;1100 return a + b;
1101 }1101 }
...@@ -1170,7 +1170,7 @@ test "suspend in for loop" {...@@ -1170,7 +1170,7 @@ test "suspend in for loop" {
1170 global_frame = @frame();1170 global_frame = @frame();
1171 var sum: u32 = 0;1171 var sum: u32 = 0;
1172 for (stuff) |x| {1172 for (stuff) |x| {
1173 suspend;1173 suspend {}
1174 sum += x;1174 sum += x;
1175 }1175 }
1176 global_frame = null;1176 global_frame = null;
...@@ -1197,7 +1197,7 @@ test "suspend in while loop" {...@@ -1197,7 +1197,7 @@ test "suspend in while loop" {
1197 global_frame = @frame();1197 global_frame = @frame();
1198 defer global_frame = null;1198 defer global_frame = null;
1199 while (stuff) |val| {1199 while (stuff) |val| {
1200 suspend;1200 suspend {}
1201 return val;1201 return val;
1202 }1202 }
1203 return 0;1203 return 0;
...@@ -1206,7 +1206,7 @@ test "suspend in while loop" {...@@ -1206,7 +1206,7 @@ test "suspend in while loop" {
1206 global_frame = @frame();1206 global_frame = @frame();
1207 defer global_frame = null;1207 defer global_frame = null;
1208 while (stuff) |val| {1208 while (stuff) |val| {
1209 suspend;1209 suspend {}
1210 return val;1210 return val;
1211 } else |err| {1211 } else |err| {
1212 return 0;1212 return 0;
...@@ -1339,7 +1339,7 @@ test "async function passed 0-bit arg after non-0-bit arg" {...@@ -1339,7 +1339,7 @@ test "async function passed 0-bit arg after non-0-bit arg" {
13391339
1340 fn bar(x: i32, args: anytype) anyerror!void {1340 fn bar(x: i32, args: anytype) anyerror!void {
1341 global_frame = @frame();1341 global_frame = @frame();
1342 suspend;1342 suspend {}
1343 global_int = x;1343 global_int = x;
1344 }1344 }
1345 };1345 };
...@@ -1361,7 +1361,7 @@ test "async function passed align(16) arg after align(8) arg" {...@@ -1361,7 +1361,7 @@ test "async function passed align(16) arg after align(8) arg" {
1361 fn bar(x: u64, args: anytype) anyerror!void {1361 fn bar(x: u64, args: anytype) anyerror!void {
1362 expect(x == 10);1362 expect(x == 10);
1363 global_frame = @frame();1363 global_frame = @frame();
1364 suspend;1364 suspend {}
1365 global_int = args[0];1365 global_int = args[0];
1366 }1366 }
1367 };1367 };
...@@ -1383,7 +1383,7 @@ test "async function call resolves target fn frame, comptime func" {...@@ -1383,7 +1383,7 @@ test "async function call resolves target fn frame, comptime func" {
13831383
1384 fn bar() anyerror!void {1384 fn bar() anyerror!void {
1385 global_frame = @frame();1385 global_frame = @frame();
1386 suspend;1386 suspend {}
1387 global_int += 1;1387 global_int += 1;
1388 }1388 }
1389 };1389 };
...@@ -1406,7 +1406,7 @@ test "async function call resolves target fn frame, runtime func" {...@@ -1406,7 +1406,7 @@ test "async function call resolves target fn frame, runtime func" {
14061406
1407 fn bar() anyerror!void {1407 fn bar() anyerror!void {
1408 global_frame = @frame();1408 global_frame = @frame();
1409 suspend;1409 suspend {}
1410 global_int += 1;1410 global_int += 1;
1411 }1411 }
1412 };1412 };
...@@ -1430,7 +1430,7 @@ test "properly spill optional payload capture value" {...@@ -1430,7 +1430,7 @@ test "properly spill optional payload capture value" {
14301430
1431 fn bar() void {1431 fn bar() void {
1432 global_frame = @frame();1432 global_frame = @frame();
1433 suspend;1433 suspend {}
1434 global_int += 1;1434 global_int += 1;
1435 }1435 }
1436 };1436 };
...@@ -1466,13 +1466,13 @@ test "handle defer interfering with return value spill" {...@@ -1466,13 +1466,13 @@ test "handle defer interfering with return value spill" {
14661466
1467 fn bar() anyerror!void {1467 fn bar() anyerror!void {
1468 global_frame1 = @frame();1468 global_frame1 = @frame();
1469 suspend;1469 suspend {}
1470 return error.Bad;1470 return error.Bad;
1471 }1471 }
14721472
1473 fn baz() void {1473 fn baz() void {
1474 global_frame2 = @frame();1474 global_frame2 = @frame();
1475 suspend;1475 suspend {}
1476 baz_happened = true;1476 baz_happened = true;
1477 }1477 }
1478 };1478 };
...@@ -1497,7 +1497,7 @@ test "take address of temporary async frame" {...@@ -1497,7 +1497,7 @@ test "take address of temporary async frame" {
14971497
1498 fn foo(arg: i32) i32 {1498 fn foo(arg: i32) i32 {
1499 global_frame = @frame();1499 global_frame = @frame();
1500 suspend;1500 suspend {}
1501 return arg + 1234;1501 return arg + 1234;
1502 }1502 }
15031503
...@@ -1520,7 +1520,7 @@ test "nosuspend await" {...@@ -1520,7 +1520,7 @@ test "nosuspend await" {
15201520
1521 fn foo(want_suspend: bool) i32 {1521 fn foo(want_suspend: bool) i32 {
1522 if (want_suspend) {1522 if (want_suspend) {
1523 suspend;1523 suspend {}
1524 }1524 }
1525 return 42;1525 return 42;
1526 }1526 }
...@@ -1569,11 +1569,11 @@ test "nosuspend on async function calls" {...@@ -1569,11 +1569,11 @@ test "nosuspend on async function calls" {
1569// };1569// };
1570// const S1 = struct {1570// const S1 = struct {
1571// fn c() S0 {1571// fn c() S0 {
1572// suspend;1572// suspend {}
1573// return S0{};1573// return S0{};
1574// }1574// }
1575// fn d() !S0 {1575// fn d() !S0 {
1576// suspend;1576// suspend {}
1577// return S0{};1577// return S0{};
1578// }1578// }
1579// };1579// };
...@@ -1591,11 +1591,11 @@ test "nosuspend resume async function calls" {...@@ -1591,11 +1591,11 @@ test "nosuspend resume async function calls" {
1591 };1591 };
1592 const S1 = struct {1592 const S1 = struct {
1593 fn c() S0 {1593 fn c() S0 {
1594 suspend;1594 suspend {}
1595 return S0{};1595 return S0{};
1596 }1596 }
1597 fn d() !S0 {1597 fn d() !S0 {
1598 suspend;1598 suspend {}
1599 return S0{};1599 return S0{};
1600 }1600 }
1601 };1601 };