Commit 0aede1a8fc

LemonBoy <thatlemon@gmail.com>
2021-04-24 10:20:16
stage1: Require a block after suspend
Closes #8603
1 parent 4ec6d17
doc/langref.html.in
@@ -6528,7 +6528,7 @@ test "suspend with no resume" {
 
 fn func() void {
     x += 1;
-    suspend;
+    suspend {}
     // This line is never reached because the suspend has no matching resume.
     x += 1;
 }
@@ -6593,7 +6593,7 @@ fn testResumeFromSuspend(my_result: *i32) void {
         resume @frame();
     }
     my_result.* += 1;
-    suspend;
+    suspend {}
     my_result.* += 1;
 }
       {#code_end#}
@@ -6632,7 +6632,7 @@ fn amain() void {
 }
 
 fn func() void {
-    suspend;
+    suspend {}
 }
       {#code_end#}
       <p>
@@ -6934,7 +6934,7 @@ test "async fn pointer in a struct field" {
 fn func(y: *i32) void {
     defer y.* += 2;
     y.* += 1;
-    suspend;
+    suspend {}
 }
       {#code_end#}
       {#header_close#}
@@ -7667,7 +7667,7 @@ test "heap allocated frame" {
 }
 
 fn func() void {
-    suspend;
+    suspend {}
 }
       {#code_end#}
       {#header_close#}
lib/std/event/rwlock.zig
@@ -264,7 +264,7 @@ var shared_test_data = [1]i32{0} ** 10;
 var shared_test_index: usize = 0;
 var shared_count: usize = 0;
 fn writeRunner(lock: *RwLock) callconv(.Async) void {
-    suspend; // resumed by onNextTick
+    suspend {} // resumed by onNextTick
 
     var i: usize = 0;
     while (i < shared_test_data.len) : (i += 1) {
@@ -281,7 +281,7 @@ fn writeRunner(lock: *RwLock) callconv(.Async) void {
     }
 }
 fn readRunner(lock: *RwLock) callconv(.Async) void {
-    suspend; // resumed by onNextTick
+    suspend {} // resumed by onNextTick
     std.time.sleep(1);
 
     var i: usize = 0;
lib/std/zig/parse.zig
@@ -852,7 +852,7 @@ const Parser = struct {
     ///     <- KEYWORD_comptime? VarDecl
     ///      / KEYWORD_comptime BlockExprStatement
     ///      / KEYWORD_nosuspend BlockExprStatement
-    ///      / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
+    ///      / KEYWORD_suspend BlockExprStatement
     ///      / KEYWORD_defer BlockExprStatement
     ///      / KEYWORD_errdefer Payload? BlockExprStatement
     ///      / IfStatement
@@ -891,16 +891,11 @@ const Parser = struct {
                 });
             },
             .keyword_suspend => {
-                const token = p.nextToken();
-                const block_expr: Node.Index = if (p.eatToken(.semicolon) != null)
-                    0
-                else
-                    try p.expectBlockExprStatement();
                 return p.addNode(.{
                     .tag = .@"suspend",
-                    .main_token = token,
+                    .main_token = p.nextToken(),
                     .data = .{
-                        .lhs = block_expr,
+                        .lhs = try p.expectBlockExprStatement(),
                         .rhs = undefined,
                     },
                 });
lib/std/zig/parser_test.zig
@@ -3665,9 +3665,9 @@ test "zig fmt: async functions" {
         \\fn simpleAsyncFn() void {
         \\    const a = async a.b();
         \\    x += 1;
-        \\    suspend;
+        \\    suspend {}
         \\    x += 1;
-        \\    suspend;
+        \\    suspend {}
         \\    const p: anyframe->void = async simpleAsyncFn() catch unreachable;
         \\    await p;
         \\}
@@ -5022,6 +5022,18 @@ test "recovery: invalid comptime" {
     });
 }
 
+test "recovery: missing block after suspend" {
+    try testError(
+        \\fn foo() void {
+        \\    suspend;
+        \\    nosuspend;
+        \\}
+    , &[_]Error{
+        .expected_block_or_expr,
+        .expected_block_or_expr,
+    });
+}
+
 test "recovery: missing block after for/while loops" {
     try testError(
         \\test "" { while (foo) }
@@ -5165,7 +5177,7 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {
     var tree = try std.zig.parse(std.testing.allocator, source);
     defer tree.deinit(std.testing.allocator);
 
-    std.testing.expect(tree.errors.len == expected_errors.len);
+    std.testing.expectEqual(expected_errors.len, tree.errors.len);
     for (expected_errors) |expected, i| {
         std.testing.expectEqual(expected, tree.errors[i].tag);
     }
lib/std/zig/render.zig
@@ -255,24 +255,13 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I
             try renderToken(ais, tree, defer_token, .space);
             return renderExpression(gpa, ais, tree, expr, space);
         },
-        .@"comptime", .@"nosuspend" => {
+        .@"comptime", .@"suspend", .@"nosuspend" => {
             const comptime_token = main_tokens[node];
             const block = datas[node].lhs;
             try renderToken(ais, tree, comptime_token, .space);
             return renderExpression(gpa, ais, tree, block, space);
         },
 
-        .@"suspend" => {
-            const suspend_token = main_tokens[node];
-            const body = datas[node].lhs;
-            if (body != 0) {
-                try renderToken(ais, tree, suspend_token, .space);
-                return renderExpression(gpa, ais, tree, body, space);
-            } else {
-                return renderToken(ais, tree, suspend_token, space);
-            }
-        },
-
         .@"catch" => {
             const main_token = main_tokens[node];
             const fallback_first = tree.firstToken(datas[node].rhs);
src/stage1/ir.cpp
@@ -9534,7 +9534,7 @@ static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNo
 
     Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope);
     // purposefully pass null for result_loc and let EndExpr handle it
-    return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
+    return ir_gen_node_extra(irb, node->data.nosuspend_expr.expr, child_scope, lval, nullptr);
 }
 
 static 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
     }
 
     IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node);
-    if (node->data.suspend.block != nullptr) {
-        ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);
-        Scope *child_scope = &suspend_scope->base;
-        IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);
-        if (susp_res == irb->codegen->invalid_inst_src)
-            return irb->codegen->invalid_inst_src;
-        ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
-    }
+    ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope);
+    Scope *child_scope = &suspend_scope->base;
+    IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope);
+    if (susp_res == irb->codegen->invalid_inst_src)
+        return irb->codegen->invalid_inst_src;
+    ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res));
 
     return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin));
 }
src/stage1/parser.cpp
@@ -946,10 +946,7 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
 
     Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);
     if (suspend != nullptr) {
-        AstNode *statement = nullptr;
-        if (eat_token_if(pc, TokenIdSemicolon) == nullptr)
-            statement = ast_expect(pc, ast_parse_block_expr_statement);
-
+        AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
         AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend);
         res->data.suspend.block = statement;
         return res;
test/stage1/behavior/async_fn.zig
@@ -18,9 +18,9 @@ test "simple coroutine suspend and resume" {
 }
 fn simpleAsyncFn() void {
     global_x += 1;
-    suspend;
+    suspend {}
     global_x += 1;
-    suspend;
+    suspend {}
     global_x += 1;
 }
 
@@ -34,7 +34,7 @@ test "pass parameter to coroutine" {
 }
 fn simpleAsyncFnWithArg(delta: i32) void {
     global_y += delta;
-    suspend;
+    suspend {}
     global_y += delta;
 }
 
@@ -50,7 +50,7 @@ test "suspend at end of function" {
 
         fn suspendAtEnd() void {
             x += 1;
-            suspend;
+            suspend {}
         }
     };
     S.doTheTest();
@@ -74,11 +74,11 @@ test "local variable in async function" {
 
         fn add(a: i32, b: i32) void {
             var accum: i32 = 0;
-            suspend;
+            suspend {}
             accum += a;
-            suspend;
+            suspend {}
             accum += b;
-            suspend;
+            suspend {}
             x = accum;
         }
     };
@@ -102,7 +102,7 @@ test "calling an inferred async function" {
         }
         fn other() void {
             other_frame = @frame();
-            suspend;
+            suspend {}
             x += 1;
         }
     };
@@ -129,7 +129,7 @@ test "@frameSize" {
         }
         fn other(param: i32) void {
             var local: i32 = undefined;
-            suspend;
+            suspend {}
         }
     };
     S.doTheTest();
@@ -269,7 +269,7 @@ test "async function with dot syntax" {
         var y: i32 = 1;
         fn foo() callconv(.Async) void {
             y += 1;
-            suspend;
+            suspend {}
         }
     };
     const p = async S.foo();
@@ -298,7 +298,7 @@ fn doTheAwait(f: anyframe->void) void {
 fn simpleAsyncFn2(y: *i32) callconv(.Async) void {
     defer y.* += 2;
     y.* += 1;
-    suspend;
+    suspend {}
 }
 
 test "@asyncCall with return type" {
@@ -312,7 +312,7 @@ test "@asyncCall with return type" {
 
         fn afunc() i32 {
             global_frame = @frame();
-            suspend;
+            suspend {}
             return 1234;
         }
     };
@@ -348,7 +348,7 @@ test "async fn with inferred error set" {
 
         fn failing() !void {
             global_frame = @frame();
-            suspend;
+            suspend {}
             return error.Fail;
         }
     };
@@ -375,7 +375,7 @@ fn nonFailing() (anyframe->anyerror!void) {
     return &Static.frame;
 }
 fn suspendThenFail() callconv(.Async) anyerror!void {
-    suspend;
+    suspend {}
     return error.Fail;
 }
 fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void {
@@ -400,7 +400,7 @@ fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void {
         resume @frame();
     }
     my_result.* += 1;
-    suspend;
+    suspend {}
     my_result.* += 1;
 }
 
@@ -421,7 +421,7 @@ test "heap allocated async function frame" {
 
         fn someFunc() void {
             x += 1;
-            suspend;
+            suspend {}
             x += 1;
         }
     };
@@ -454,7 +454,7 @@ test "async function call return value" {
 
         fn other(x: i32, y: i32) Point {
             frame = @frame();
-            suspend;
+            suspend {}
             return Point{
                 .x = x,
                 .y = y,
@@ -487,7 +487,7 @@ test "suspension points inside branching control flow" {
 
         fn func(b: bool) void {
             while (b) {
-                suspend;
+                suspend {}
                 result += 1;
             }
         }
@@ -541,7 +541,7 @@ test "pass string literal to async function" {
 
         fn hello(msg: []const u8) void {
             frame = @frame();
-            suspend;
+            suspend {}
             expectEqualStrings("hello", msg);
             ok = true;
         }
@@ -566,7 +566,7 @@ test "await inside an errdefer" {
 
         fn func() void {
             frame = @frame();
-            suspend;
+            suspend {}
         }
     };
     S.doTheTest();
@@ -590,7 +590,7 @@ test "try in an async function with error union and non-zero-bit payload" {
 
         fn theProblem() ![]u8 {
             frame = @frame();
-            suspend;
+            suspend {}
             const result = try other();
             return result;
         }
@@ -622,7 +622,7 @@ test "returning a const error from async function" {
 
         fn fetchUrl(unused: i32, url: []const u8) ![]u8 {
             frame = @frame();
-            suspend;
+            suspend {}
             ok = true;
             return error.OutOfMemory;
         }
@@ -967,7 +967,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
 
         fn failing() !void {
             global_frame = @frame();
-            suspend;
+            suspend {}
             return error.Fail;
         }
     };
@@ -977,7 +977,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
 test "@asyncCall with actual frame instead of byte buffer" {
     const S = struct {
         fn func() i32 {
-            suspend;
+            suspend {}
             return 1234;
         }
     };
@@ -993,7 +993,7 @@ test "@asyncCall using the result location inside the frame" {
         fn simple2(y: *i32) callconv(.Async) i32 {
             defer y.* += 2;
             y.* += 1;
-            suspend;
+            suspend {}
             return 1234;
         }
         fn getAnswer(f: anyframe->i32, out: *i32) void {
@@ -1095,7 +1095,7 @@ test "nosuspend function call" {
         }
         fn add(a: i32, b: i32) i32 {
             if (a > 100) {
-                suspend;
+                suspend {}
             }
             return a + b;
         }
@@ -1170,7 +1170,7 @@ test "suspend in for loop" {
             global_frame = @frame();
             var sum: u32 = 0;
             for (stuff) |x| {
-                suspend;
+                suspend {}
                 sum += x;
             }
             global_frame = null;
@@ -1197,7 +1197,7 @@ test "suspend in while loop" {
             global_frame = @frame();
             defer global_frame = null;
             while (stuff) |val| {
-                suspend;
+                suspend {}
                 return val;
             }
             return 0;
@@ -1206,7 +1206,7 @@ test "suspend in while loop" {
             global_frame = @frame();
             defer global_frame = null;
             while (stuff) |val| {
-                suspend;
+                suspend {}
                 return val;
             } else |err| {
                 return 0;
@@ -1339,7 +1339,7 @@ test "async function passed 0-bit arg after non-0-bit arg" {
 
         fn bar(x: i32, args: anytype) anyerror!void {
             global_frame = @frame();
-            suspend;
+            suspend {}
             global_int = x;
         }
     };
@@ -1361,7 +1361,7 @@ test "async function passed align(16) arg after align(8) arg" {
         fn bar(x: u64, args: anytype) anyerror!void {
             expect(x == 10);
             global_frame = @frame();
-            suspend;
+            suspend {}
             global_int = args[0];
         }
     };
@@ -1383,7 +1383,7 @@ test "async function call resolves target fn frame, comptime func" {
 
         fn bar() anyerror!void {
             global_frame = @frame();
-            suspend;
+            suspend {}
             global_int += 1;
         }
     };
@@ -1406,7 +1406,7 @@ test "async function call resolves target fn frame, runtime func" {
 
         fn bar() anyerror!void {
             global_frame = @frame();
-            suspend;
+            suspend {}
             global_int += 1;
         }
     };
@@ -1430,7 +1430,7 @@ test "properly spill optional payload capture value" {
 
         fn bar() void {
             global_frame = @frame();
-            suspend;
+            suspend {}
             global_int += 1;
         }
     };
@@ -1466,13 +1466,13 @@ test "handle defer interfering with return value spill" {
 
         fn bar() anyerror!void {
             global_frame1 = @frame();
-            suspend;
+            suspend {}
             return error.Bad;
         }
 
         fn baz() void {
             global_frame2 = @frame();
-            suspend;
+            suspend {}
             baz_happened = true;
         }
     };
@@ -1497,7 +1497,7 @@ test "take address of temporary async frame" {
 
         fn foo(arg: i32) i32 {
             global_frame = @frame();
-            suspend;
+            suspend {}
             return arg + 1234;
         }
 
@@ -1520,7 +1520,7 @@ test "nosuspend await" {
 
         fn foo(want_suspend: bool) i32 {
             if (want_suspend) {
-                suspend;
+                suspend {}
             }
             return 42;
         }
@@ -1569,11 +1569,11 @@ test "nosuspend on async function calls" {
 //     };
 //     const S1 = struct {
 //         fn c() S0 {
-//             suspend;
+//             suspend {}
 //             return S0{};
 //         }
 //         fn d() !S0 {
-//             suspend;
+//             suspend {}
 //             return S0{};
 //         }
 //     };
@@ -1591,11 +1591,11 @@ test "nosuspend resume async function calls" {
     };
     const S1 = struct {
         fn c() S0 {
-            suspend;
+            suspend {}
             return S0{};
         }
         fn d() !S0 {
-            suspend;
+            suspend {}
             return S0{};
         }
     };
test/compile_errors.zig
@@ -1021,7 +1021,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\export fn entry() void {
         \\    nosuspend {
         \\        const bar = async foo();
-        \\        suspend;
+        \\        suspend {}
         \\        resume bar;
         \\    }
         \\}
@@ -2120,7 +2120,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    non_async_fn = func;
         \\}
         \\fn func() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     , &[_][]const u8{
         "tmp.zig:5:1: error: 'func' cannot be async",
@@ -2198,7 +2198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    var x: anyframe = &f;
         \\}
         \\fn func() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     , &[_][]const u8{
         "tmp.zig:3:12: error: expected type 'anyframe', found '*const @Frame(func)'",
@@ -2231,10 +2231,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    frame = async bar();
         \\}
         \\fn foo() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
         \\fn bar() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     , &[_][]const u8{
         "tmp.zig:3:13: error: expected type '*@Frame(bar)', found '*@Frame(foo)'",
@@ -2269,7 +2269,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    var result = await frame;
         \\}
         \\fn func() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     , &[_][]const u8{
         "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
@@ -2347,7 +2347,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         \\    bar();
         \\}
         \\fn bar() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     , &[_][]const u8{
         "tmp.zig:1:1: error: function with calling convention 'C' cannot be async",
test/runtime_safety.zig
@@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
 
         cases.addRuntimeSafety("switch on corrupted enum value",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\const E = enum(u32) {
             \\    X = 1,
             \\};
@@ -28,7 +28,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
 
         cases.addRuntimeSafety("switch on corrupted union value",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\const U = union(enum(u32)) {
             \\    X: u8,
             \\};
@@ -54,7 +54,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
 
         cases.addRuntimeSafety("@tagName on corrupted enum value",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\const E = enum(u32) {
             \\    X = 1,
             \\};
@@ -67,7 +67,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
 
         cases.addRuntimeSafety("@tagName on corrupted union value",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\const U = union(enum(u32)) {
             \\    X: u8,
             \\};
@@ -92,7 +92,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
 
         cases.addRuntimeSafety("slicing operator with sentinel",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\pub fn main() void {
             \\    var buf = [4]u8{'a','b','c',0};
             \\    const slice = buf[0..4 :0];
@@ -100,7 +100,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         );
         cases.addRuntimeSafety("slicing operator with sentinel",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\pub fn main() void {
             \\    var buf = [4]u8{'a','b','c',0};
             \\    const slice = buf[0..:0];
@@ -108,7 +108,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         );
         cases.addRuntimeSafety("slicing operator with sentinel",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\pub fn main() void {
             \\    var buf_zero = [0]u8{};
             \\    const slice = buf_zero[0..0 :0];
@@ -116,7 +116,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         );
         cases.addRuntimeSafety("slicing operator with sentinel",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\pub fn main() void {
             \\    var buf_zero = [0]u8{};
             \\    const slice = buf_zero[0..:0];
@@ -124,7 +124,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         );
         cases.addRuntimeSafety("slicing operator with sentinel",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\pub fn main() void {
             \\    var buf_sentinel = [2:0]u8{'a','b'};
             \\    @ptrCast(*[3]u8, &buf_sentinel)[2] = 0;
@@ -133,7 +133,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         );
         cases.addRuntimeSafety("slicing operator with sentinel",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\pub fn main() void {
             \\    var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };
             \\    const slice = buf_slice[0..3 :0];
@@ -141,7 +141,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         );
         cases.addRuntimeSafety("slicing operator with sentinel",
             \\const std = @import("std");
-            ++ check_panic_msg ++
+        ++ check_panic_msg ++
             \\pub fn main() void {
             \\    var buf_slice: []const u8 = &[3]u8{ 'a', 'b', 0 };
             \\    const slice = buf_slice[0.. :0];
@@ -367,7 +367,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\}
         \\fn add(a: i32, b: i32) i32 {
         \\    if (a > 100) {
-        \\        suspend;
+        \\        suspend {}
         \\    }
         \\    return a + b;
         \\}
@@ -407,7 +407,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\    var frame = @asyncCall(&bytes, {}, ptr, .{});
         \\}
         \\fn other() callconv(.Async) void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     );
 
@@ -424,7 +424,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\    await frame;
         \\}
         \\fn other() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     );
 
@@ -440,7 +440,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\    other();
         \\}
         \\fn other() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     );
 
@@ -454,7 +454,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\    resume p; //bad
         \\}
         \\fn suspendOnce() void {
-        \\    suspend;
+        \\    suspend {}
         \\}
     );
 
@@ -1019,7 +1019,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\}
         \\
         \\fn failing() anyerror!void {
-        \\    suspend;
+        \\    suspend {}
         \\    return second();
         \\}
         \\