authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-07 11:22:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-07 13:39:16-07:00
log40d11cc25a469dc6bb0f9fbba4d05e7210a23b3f
tree8f3ece572204f0ae02efe5f07581530db302dc1b
parent31e46be74360f7bf6509bd8826690318974175c0

remove `async` and `await` keywords

Also remove `@frameSize`, closing #3654. While the other machinery might remain depending on #23446, it is settled that there will not be `async`/ `await` keywords in the language.

48 files changed, 24 insertions(+), 2913 deletions(-)

doc/langref.html.in+6-40
......@@ -4279,16 +4279,9 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
42794279 {#header_close#}
42804280
42814281 {#header_open|Async Functions#}
4282 <p>Async functions regressed with the release of 0.11.0. Their future in
4283 the Zig language is unclear due to multiple unsolved problems:</p>
4284 <ul>
4285 <li>LLVM's lack of ability to optimize them.</li>
4286 <li>Third-party debuggers' lack of ability to debug them.</li>
4287 <li><a href="https://github.com/ziglang/zig/issues/5913">The cancellation problem</a>.</li>
4288 <li>Async function pointers preventing the stack size from being known.</li>
4289 </ul>
4290 <p>These problems are surmountable, but it will take time. The Zig team
4291 is currently focused on other priorities.</p>
4282 <p>Async functions regressed with the release of 0.11.0. The current plan is to
4283 reintroduce them as a lower level primitive that powers I/O implementations.</p>
4284 <p>Tracking issue: <a href="https://github.com/ziglang/zig/issues/23446">Proposal: stackless coroutines as low-level primitives</a></p>
42924285 {#header_close#}
42934286
42944287 {#header_open|Builtin Functions|2col#}
......@@ -7372,29 +7365,6 @@ fn readU32Be() u32 {}
73727365 </ul>
73737366 </td>
73747367 </tr>
7375 <tr>
7376 <th scope="row">
7377 <pre>{#syntax#}async{#endsyntax#}</pre>
7378 </th>
7379 <td>
7380 {#syntax#}async{#endsyntax#} can be used before a function call to get a pointer to the function's frame when it suspends.
7381 <ul>
7382 <li>See also {#link|Async Functions#}</li>
7383 </ul>
7384 </td>
7385 </tr>
7386 <tr>
7387 <th scope="row">
7388 <pre>{#syntax#}await{#endsyntax#}</pre>
7389 </th>
7390 <td>
7391 {#syntax#}await{#endsyntax#} can be used to suspend the current function until the frame provided after the {#syntax#}await{#endsyntax#} completes.
7392 {#syntax#}await{#endsyntax#} copies the value returned from the target function's frame to the caller.
7393 <ul>
7394 <li>See also {#link|Async Functions#}</li>
7395 </ul>
7396 </td>
7397 </tr>
73987368 <tr>
73997369 <th scope="row">
74007370 <pre>{#syntax#}break{#endsyntax#}</pre>
......@@ -8006,8 +7976,7 @@ TypeExpr <- PrefixTypeOp* ErrorUnionExpr
80067976ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
80077977
80087978SuffixExpr
8009 <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
8010 / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
7979 <- PrimaryTypeExpr (SuffixOp / FnCallArguments)*
80117980
80127981PrimaryTypeExpr
80137982 <- BUILTINIDENTIFIER FnCallArguments
......@@ -8183,7 +8152,6 @@ PrefixOp
81838152 / MINUSPERCENT
81848153 / AMPERSAND
81858154 / KEYWORD_try
8186 / KEYWORD_await
81878155
81888156PrefixTypeOp
81898157 <- QUESTIONMARK
......@@ -8404,8 +8372,6 @@ KEYWORD_and <- 'and' end_of_word
84048372KEYWORD_anyframe <- 'anyframe' end_of_word
84058373KEYWORD_anytype <- 'anytype' end_of_word
84068374KEYWORD_asm <- 'asm' end_of_word
8407KEYWORD_async <- 'async' end_of_word
8408KEYWORD_await <- 'await' end_of_word
84098375KEYWORD_break <- 'break' end_of_word
84108376KEYWORD_callconv <- 'callconv' end_of_word
84118377KEYWORD_catch <- 'catch' end_of_word
......@@ -8448,8 +8414,8 @@ KEYWORD_volatile <- 'volatile' end_of_word
84488414KEYWORD_while <- 'while' end_of_word
84498415
84508416keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and
8451 / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async
8452 / KEYWORD_await / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch
8417 / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm
8418 / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch
84538419 / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer
84548420 / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export
84558421 / KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if
lib/compiler/reduce/Walk.zig-5
......@@ -335,7 +335,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
335335 .address_of,
336336 .@"try",
337337 .@"resume",
338 .@"await",
339338 .deref,
340339 => {
341340 return walkExpression(w, ast.nodeData(node).node);
......@@ -379,12 +378,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
379378
380379 .call_one,
381380 .call_one_comma,
382 .async_call_one,
383 .async_call_one_comma,
384381 .call,
385382 .call_comma,
386 .async_call,
387 .async_call_comma,
388383 => {
389384 var buf: [1]Ast.Node.Index = undefined;
390385 return walkCall(w, ast.fullCall(&buf, node).?);
lib/docs/wasm/Walk.zig-9
......@@ -238,12 +238,8 @@ pub const File = struct {
238238
239239 .call_one,
240240 .call_one_comma,
241 .async_call_one,
242 .async_call_one_comma,
243241 .call,
244242 .call_comma,
245 .async_call,
246 .async_call_comma,
247243 => {
248244 var buf: [1]Ast.Node.Index = undefined;
249245 return categorize_call(file_index, node, ast.fullCall(&buf, node).?);
......@@ -743,7 +739,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
743739 .@"comptime",
744740 .@"nosuspend",
745741 .@"suspend",
746 .@"await",
747742 .@"resume",
748743 .@"try",
749744 => try expr(w, scope, parent_decl, ast.nodeData(node).node),
......@@ -806,12 +801,8 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
806801
807802 .call_one,
808803 .call_one_comma,
809 .async_call_one,
810 .async_call_one_comma,
811804 .call,
812805 .call_comma,
813 .async_call,
814 .async_call_comma,
815806 => {
816807 var buf: [1]Ast.Node.Index = undefined;
817808 const full = ast.fullCall(&buf, node).?;
lib/docs/wasm/html_render.zig-2
......@@ -101,8 +101,6 @@ pub fn fileSourceHtml(
101101 .keyword_align,
102102 .keyword_and,
103103 .keyword_asm,
104 .keyword_async,
105 .keyword_await,
106104 .keyword_break,
107105 .keyword_catch,
108106 .keyword_comptime,
lib/std/builtin.zig+1-12
......@@ -199,8 +199,6 @@ pub const CallingConvention = union(enum(u8)) {
199199 pub const C: CallingConvention = .c;
200200 /// Deprecated; use `.naked`.
201201 pub const Naked: CallingConvention = .naked;
202 /// Deprecated; use `.@"async"`.
203 pub const Async: CallingConvention = .@"async";
204202 /// Deprecated; use `.@"inline"`.
205203 pub const Inline: CallingConvention = .@"inline";
206204 /// Deprecated; use `.x86_64_interrupt`, `.x86_interrupt`, or `.avr_interrupt`.
......@@ -866,32 +864,23 @@ pub const WasiExecModel = enum {
866864pub const CallModifier = enum {
867865 /// Equivalent to function call syntax.
868866 auto,
869
870 /// Equivalent to async keyword used with function call syntax.
871 async_kw,
872
873867 /// Prevents tail call optimization. This guarantees that the return
874868 /// address will point to the callsite, as opposed to the callsite's
875869 /// callsite. If the call is otherwise required to be tail-called
876870 /// or inlined, a compile error is emitted instead.
877871 never_tail,
878
879872 /// Guarantees that the call will not be inlined. If the call is
880873 /// otherwise required to be inlined, a compile error is emitted instead.
881874 never_inline,
882
883875 /// Asserts that the function call will not suspend. This allows a
884876 /// non-async function to call an async function.
885 no_async,
886
877 no_suspend,
887878 /// Guarantees that the call will be generated with tail call optimization.
888879 /// If this is not possible, a compile error is emitted instead.
889880 always_tail,
890
891881 /// Guarantees that the call will be inlined at the callsite.
892882 /// If this is not possible, a compile error is emitted instead.
893883 always_inline,
894
895884 /// Evaluates the call at compile-time. If the call cannot be completed at
896885 /// compile-time, a compile error is emitted instead.
897886 compile_time,
lib/std/zig/Ast.zig+7-64
......@@ -606,7 +606,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
606606 .negation_wrap,
607607 .address_of,
608608 .@"try",
609 .@"await",
610609 .optional_type,
611610 .@"switch",
612611 .switch_comma,
......@@ -763,20 +762,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
763762 return main_token - end_offset;
764763 },
765764
766 .async_call_one,
767 .async_call_one_comma,
768 => {
769 end_offset += 1; // async token
770 n = tree.nodeData(n).node_and_opt_node[0];
771 },
772
773 .async_call,
774 .async_call_comma,
775 => {
776 end_offset += 1; // async token
777 n = tree.nodeData(n).node_and_extra[0];
778 },
779
780765 .container_field_init,
781766 .container_field_align,
782767 .container_field,
......@@ -903,7 +888,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
903888 .negation_wrap,
904889 .address_of,
905890 .@"try",
906 .@"await",
907891 .optional_type,
908892 .@"suspend",
909893 .@"resume",
......@@ -1022,7 +1006,7 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10221006 };
10231007 },
10241008
1025 .call, .async_call => {
1009 .call => {
10261010 _, const extra_index = tree.nodeData(n).node_and_extra;
10271011 const params = tree.extraData(extra_index, Node.SubRange);
10281012 assert(params.start != params.end);
......@@ -1041,7 +1025,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10411025 }
10421026 },
10431027 .call_comma,
1044 .async_call_comma,
10451028 .tagged_union_enum_tag_trailing,
10461029 => {
10471030 _, const extra_index = tree.nodeData(n).node_and_extra;
......@@ -1122,7 +1105,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
11221105 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member
11231106 },
11241107 .call_one,
1125 .async_call_one,
11261108 => {
11271109 _, const first_param = tree.nodeData(n).node_and_opt_node;
11281110 end_offset += 1; // for the rparen
......@@ -1271,7 +1253,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
12711253 n = first_element;
12721254 },
12731255 .call_one_comma,
1274 .async_call_one_comma,
12751256 .struct_init_one_comma,
12761257 => {
12771258 _, const first_field = tree.nodeData(n).node_and_opt_node;
......@@ -1988,21 +1969,21 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {
19881969pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {
19891970 const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;
19901971 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
1991 return tree.fullCallComponents(.{
1972 return .{ .ast = .{
19921973 .lparen = tree.nodeMainToken(node),
19931974 .fn_expr = fn_expr,
19941975 .params = params,
1995 });
1976 } };
19961977}
19971978
19981979pub fn callFull(tree: Ast, node: Node.Index) full.Call {
19991980 const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;
20001981 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
2001 return tree.fullCallComponents(.{
1982 return .{ .ast = .{
20021983 .lparen = tree.nodeMainToken(node),
20031984 .fn_expr = fn_expr,
20041985 .params = params,
2005 });
1986 } };
20061987}
20071988
20081989fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {
......@@ -2336,18 +2317,6 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
23362317 return result;
23372318}
23382319
2339fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {
2340 var result: full.Call = .{
2341 .ast = info,
2342 .async_token = null,
2343 };
2344 const first_token = tree.firstToken(info.fn_expr);
2345 if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) {
2346 result.async_token = first_token - 1;
2347 }
2348 return result;
2349}
2350
23512320pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
23522321 return switch (tree.nodeTag(node)) {
23532322 .global_var_decl => tree.globalVarDecl(node),
......@@ -2488,8 +2457,8 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
24882457
24892458pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {
24902459 return switch (tree.nodeTag(node)) {
2491 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
2492 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),
2460 .call, .call_comma => tree.callFull(node),
2461 .call_one, .call_one_comma => tree.callOne(buffer, node),
24932462 else => null,
24942463 };
24952464}
......@@ -2882,7 +2851,6 @@ pub const full = struct {
28822851
28832852 pub const Call = struct {
28842853 ast: Components,
2885 async_token: ?TokenIndex,
28862854
28872855 pub const Components = struct {
28882856 lparen: TokenIndex,
......@@ -3301,8 +3269,6 @@ pub const Node = struct {
33013269 address_of,
33023270 /// `try expr`. The `main_token` field is the `try` token.
33033271 @"try",
3304 /// `await expr`. The `main_token` field is the `await` token.
3305 @"await",
33063272 /// `?expr`. The `main_token` field is the `?` token.
33073273 optional_type,
33083274 /// `[lhs]rhs`. The `main_token` field is the `[` token.
......@@ -3498,17 +3464,6 @@ pub const Node = struct {
34983464 /// Same as `call_one` except there is known to be a trailing comma
34993465 /// before the final rparen.
35003466 call_one_comma,
3501 /// `async a(b)`, `async a()`.
3502 ///
3503 /// The `data` field is a `.node_and_opt_node`:
3504 /// 1. a `Node.Index` to the function expression.
3505 /// 2. a `Node.OptionalIndex` to the first argument, if any.
3506 ///
3507 /// The `main_token` field is the `(` token.
3508 async_call_one,
3509 /// Same as `async_call_one` except there is known to be a trailing
3510 /// comma before the final rparen.
3511 async_call_one_comma,
35123467 /// `a(b, c, d)`.
35133468 ///
35143469 /// The `data` field is a `.node_and_extra`:
......@@ -3521,18 +3476,6 @@ pub const Node = struct {
35213476 /// Same as `call` except there is known to be a trailing comma before
35223477 /// the final rparen.
35233478 call_comma,
3524 /// `async a(b, c, d)`.
3525 ///
3526 /// The `data` field is a `.node_and_extra`:
3527 /// 1. a `Node.Index` to the function expression.
3528 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3529 /// each argument.
3530 ///
3531 /// The `main_token` field is the `(` token.
3532 async_call,
3533 /// Same as `async_call` except there is known to be a trailing comma
3534 /// before the final rparen.
3535 async_call_comma,
35363479 /// `switch(a) {}`.
35373480 ///
35383481 /// The `data` field is a `.node_and_extra`:
lib/std/zig/AstGen.zig+1-69
......@@ -510,12 +510,8 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
510510 .number_literal,
511511 .call,
512512 .call_comma,
513 .async_call,
514 .async_call_comma,
515513 .call_one,
516514 .call_one_comma,
517 .async_call_one,
518 .async_call_one_comma,
519515 .unreachable_literal,
520516 .@"return",
521517 .@"if",
......@@ -547,7 +543,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
547543 .merge_error_sets,
548544 .switch_range,
549545 .for_range,
550 .@"await",
551546 .bit_not,
552547 .negation,
553548 .negation_wrap,
......@@ -836,12 +831,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
836831
837832 .call_one,
838833 .call_one_comma,
839 .async_call_one,
840 .async_call_one_comma,
841834 .call,
842835 .call_comma,
843 .async_call,
844 .async_call_comma,
845836 => {
846837 var buf: [1]Ast.Node.Index = undefined;
847838 return callExpr(gz, scope, ri, .none, node, tree.fullCall(&buf, node).?);
......@@ -1114,7 +1105,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11141105
11151106 .@"nosuspend" => return nosuspendExpr(gz, scope, ri, node),
11161107 .@"suspend" => return suspendExpr(gz, scope, node),
1117 .@"await" => return awaitExpr(gz, scope, ri, node),
11181108 .@"resume" => return resumeExpr(gz, scope, ri, node),
11191109
11201110 .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),
......@@ -1259,33 +1249,6 @@ fn suspendExpr(
12591249 return suspend_inst.toRef();
12601250}
12611251
1262fn awaitExpr(
1263 gz: *GenZir,
1264 scope: *Scope,
1265 ri: ResultInfo,
1266 node: Ast.Node.Index,
1267) InnerError!Zir.Inst.Ref {
1268 const astgen = gz.astgen;
1269 const tree = astgen.tree;
1270 const rhs_node = tree.nodeData(node).node;
1271
1272 if (gz.suspend_node.unwrap()) |suspend_node| {
1273 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
1274 try astgen.errNoteNode(suspend_node, "suspend block here", .{}),
1275 });
1276 }
1277 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
1278 const result = if (gz.nosuspend_node != .none)
1279 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
1280 .node = gz.nodeIndexToRelative(node),
1281 .operand = operand,
1282 })
1283 else
1284 try gz.addUnNode(.@"await", operand, node);
1285
1286 return rvalue(gz, ri, result, node);
1287}
1288
12891252fn resumeExpr(
12901253 gz: *GenZir,
12911254 scope: *Scope,
......@@ -2853,7 +2816,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
28532816 .tag_name,
28542817 .type_name,
28552818 .frame_type,
2856 .frame_size,
28572819 .int_from_float,
28582820 .float_from_int,
28592821 .ptr_from_int,
......@@ -2887,7 +2849,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
28872849 .min,
28882850 .c_import,
28892851 .@"resume",
2890 .@"await",
28912852 .ret_err_value_code,
28922853 .ret_ptr,
28932854 .ret_type,
......@@ -9501,7 +9462,6 @@ fn builtinCall(
95019462 .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name),
95029463 .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name),
95039464 .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type),
9504 .frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size),
95059465
95069466 .int_from_float => return typeCast(gz, scope, ri, node, params[0], .int_from_float, builtin_name),
95079467 .float_from_int => return typeCast(gz, scope, ri, node, params[0], .float_from_int, builtin_name),
......@@ -9767,16 +9727,6 @@ fn builtinCall(
97679727 });
97689728 return rvalue(gz, ri, result, node);
97699729 },
9770 .async_call => {
9771 const result = try gz.addExtendedPayload(.builtin_async_call, Zir.Inst.AsyncCall{
9772 .node = gz.nodeIndexToRelative(node),
9773 .frame_buffer = try expr(gz, scope, .{ .rl = .none }, params[0]),
9774 .result_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
9775 .fn_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]),
9776 .args = try expr(gz, scope, .{ .rl = .none }, params[3]),
9777 });
9778 return rvalue(gz, ri, result, node);
9779 },
97809730 .Vector => {
97819731 const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
97829732 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .type),
......@@ -10175,11 +10125,8 @@ fn callExpr(
1017510125
1017610126 const callee = try calleeExpr(gz, scope, ri.rl, override_decl_literal_type, call.ast.fn_expr);
1017710127 const modifier: std.builtin.CallModifier = blk: {
10178 if (call.async_token != null) {
10179 break :blk .async_kw;
10180 }
1018110128 if (gz.nosuspend_node != .none) {
10182 break :blk .no_async;
10129 break :blk .no_suspend;
1018310130 }
1018410131 break :blk .auto;
1018510132 };
......@@ -10483,12 +10430,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1048310430 .switch_comma,
1048410431 .call_one,
1048510432 .call_one_comma,
10486 .async_call_one,
10487 .async_call_one_comma,
1048810433 .call,
1048910434 .call_comma,
10490 .async_call,
10491 .async_call_comma,
1049210435 => return .maybe,
1049310436
1049410437 .@"return",
......@@ -10613,7 +10556,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1061310556
1061410557 // Forward the question to the LHS sub-expression.
1061510558 .@"try",
10616 .@"await",
1061710559 .@"comptime",
1061810560 .@"nosuspend",
1061910561 => node = tree.nodeData(node).node,
......@@ -10803,12 +10745,8 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1080310745 .switch_comma,
1080410746 .call_one,
1080510747 .call_one_comma,
10806 .async_call_one,
10807 .async_call_one_comma,
1080810748 .call,
1080910749 .call_comma,
10810 .async_call,
10811 .async_call_comma,
1081210750 .block_two,
1081310751 .block_two_semicolon,
1081410752 .block,
......@@ -10826,7 +10764,6 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1082610764
1082710765 // Forward the question to the LHS sub-expression.
1082810766 .@"try",
10829 .@"await",
1083010767 .@"comptime",
1083110768 .@"nosuspend",
1083210769 => node = tree.nodeData(node).node,
......@@ -11047,12 +10984,8 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1104710984 .switch_comma,
1104810985 .call_one,
1104910986 .call_one_comma,
11050 .async_call_one,
11051 .async_call_one_comma,
1105210987 .call,
1105310988 .call_comma,
11054 .async_call,
11055 .async_call_comma,
1105610989 .block_two,
1105710990 .block_two_semicolon,
1105810991 .block,
......@@ -11079,7 +11012,6 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1107911012
1108011013 // Forward the question to the LHS sub-expression.
1108111014 .@"try",
11082 .@"await",
1108311015 .@"comptime",
1108411016 .@"nosuspend",
1108511017 => node = tree.nodeData(node).node,
lib/std/zig/AstRlAnnotate.zig-18
......@@ -334,12 +334,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
334334
335335 .call_one,
336336 .call_one_comma,
337 .async_call_one,
338 .async_call_one_comma,
339337 .call,
340338 .call_comma,
341 .async_call,
342 .async_call_comma,
343339 => {
344340 var buf: [1]Ast.Node.Index = undefined;
345341 const full = tree.fullCall(&buf, node).?;
......@@ -353,11 +349,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
353349 .call,
354350 .call_comma,
355351 => false, // TODO: once function calls are passed result locations this will change
356 .async_call_one,
357 .async_call_one_comma,
358 .async_call,
359 .async_call_comma,
360 => ri.have_ptr, // always use result ptr for frames
361352 else => unreachable,
362353 };
363354 },
......@@ -503,7 +494,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
503494 return false;
504495 },
505496 .@"try",
506 .@"await",
507497 .@"nosuspend",
508498 => return astrl.expr(tree.nodeData(node).node, block, ri),
509499 .grouped_expression,
......@@ -948,7 +938,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
948938 .tag_name,
949939 .type_name,
950940 .Frame,
951 .frame_size,
952941 .int_from_float,
953942 .float_from_int,
954943 .ptr_from_int,
......@@ -1079,13 +1068,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
10791068 _ = try astrl.expr(args[3], block, ResultInfo.none);
10801069 return false;
10811070 },
1082 .async_call => {
1083 _ = try astrl.expr(args[0], block, ResultInfo.none);
1084 _ = try astrl.expr(args[1], block, ResultInfo.none);
1085 _ = try astrl.expr(args[2], block, ResultInfo.none);
1086 _ = try astrl.expr(args[3], block, ResultInfo.none);
1087 return false; // buffer passed as arg for frame data
1088 },
10891071 .Vector => {
10901072 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
10911073 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
lib/std/zig/BuiltinFn.zig-16
......@@ -4,7 +4,6 @@ pub const Tag = enum {
44 align_cast,
55 align_of,
66 as,
7 async_call,
87 atomic_load,
98 atomic_rmw,
109 atomic_store,
......@@ -55,7 +54,6 @@ pub const Tag = enum {
5554 frame,
5655 Frame,
5756 frame_address,
58 frame_size,
5957 has_decl,
6058 has_field,
6159 import,
......@@ -184,13 +182,6 @@ pub const list = list: {
184182 .param_count = 2,
185183 },
186184 },
187 .{
188 "@asyncCall",
189 .{
190 .tag = .async_call,
191 .param_count = 4,
192 },
193 },
194185 .{
195186 "@atomicLoad",
196187 .{
......@@ -550,13 +541,6 @@ pub const list = list: {
550541 .illegal_outside_function = true,
551542 },
552543 },
553 .{
554 "@frameSize",
555 .{
556 .tag = .frame_size,
557 .param_count = 1,
558 },
559 },
560544 .{
561545 "@hasDecl",
562546 .{
lib/std/zig/Parse.zig+1-53
......@@ -1688,7 +1688,6 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index {
16881688/// / MINUSPERCENT
16891689/// / AMPERSAND
16901690/// / KEYWORD_try
1691/// / KEYWORD_await
16921691fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
16931692 const tag: Node.Tag = switch (p.tokenTag(p.tok_i)) {
16941693 .bang => .bool_not,
......@@ -1697,7 +1696,6 @@ fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
16971696 .minus_percent => .negation_wrap,
16981697 .ampersand => .address_of,
16991698 .keyword_try => .@"try",
1700 .keyword_await => .@"await",
17011699 else => return p.parsePrimaryExpr(),
17021700 };
17031701 return try p.addNode(.{
......@@ -2385,62 +2383,12 @@ fn parseErrorUnionExpr(p: *Parse) !?Node.Index {
23852383}
23862384
23872385/// SuffixExpr
2388/// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
2389/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
2386/// <- PrimaryTypeExpr (SuffixOp / FnCallArguments)*
23902387///
23912388/// FnCallArguments <- LPAREN ExprList RPAREN
23922389///
23932390/// ExprList <- (Expr COMMA)* Expr?
23942391fn parseSuffixExpr(p: *Parse) !?Node.Index {
2395 if (p.eatToken(.keyword_async)) |_| {
2396 var res = try p.expectPrimaryTypeExpr();
2397 while (true) {
2398 res = try p.parseSuffixOp(res) orelse break;
2399 }
2400 const lparen = p.eatToken(.l_paren) orelse {
2401 try p.warn(.expected_param_list);
2402 return res;
2403 };
2404 const scratch_top = p.scratch.items.len;
2405 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2406 while (true) {
2407 if (p.eatToken(.r_paren)) |_| break;
2408 const param = try p.expectExpr();
2409 try p.scratch.append(p.gpa, param);
2410 switch (p.tokenTag(p.tok_i)) {
2411 .comma => p.tok_i += 1,
2412 .r_paren => {
2413 p.tok_i += 1;
2414 break;
2415 },
2416 .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
2417 // Likely just a missing comma; give error but continue parsing.
2418 else => try p.warn(.expected_comma_after_arg),
2419 }
2420 }
2421 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2422 const params = p.scratch.items[scratch_top..];
2423 if (params.len <= 1) {
2424 return try p.addNode(.{
2425 .tag = if (comma) .async_call_one_comma else .async_call_one,
2426 .main_token = lparen,
2427 .data = .{ .node_and_opt_node = .{
2428 res,
2429 if (params.len >= 1) params[0].toOptional() else .none,
2430 } },
2431 });
2432 } else {
2433 return try p.addNode(.{
2434 .tag = if (comma) .async_call_comma else .async_call,
2435 .main_token = lparen,
2436 .data = .{ .node_and_extra = .{
2437 res,
2438 try p.addExtra(try p.listToSpan(params)),
2439 } },
2440 });
2441 }
2442 }
2443
24442392 var res = try p.parsePrimaryTypeExpr() orelse return null;
24452393 while (true) {
24462394 const opt_suffix_op = try p.parseSuffixOp(res);
lib/std/zig/Zir.zig-26
......@@ -899,8 +899,6 @@ pub const Inst = struct {
899899 type_name,
900900 /// Implement builtin `@Frame`. Uses `un_node`.
901901 frame_type,
902 /// Implement builtin `@frameSize`. Uses `un_node`.
903 frame_size,
904902
905903 /// Implements the `@intFromFloat` builtin.
906904 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
......@@ -1044,7 +1042,6 @@ pub const Inst = struct {
10441042
10451043 /// Implements `resume` syntax. Uses `un_node` field.
10461044 @"resume",
1047 @"await",
10481045
10491046 /// A defer statement.
10501047 /// Uses the `defer` union field.
......@@ -1241,7 +1238,6 @@ pub const Inst = struct {
12411238 .tag_name,
12421239 .type_name,
12431240 .frame_type,
1244 .frame_size,
12451241 .int_from_float,
12461242 .float_from_int,
12471243 .ptr_from_int,
......@@ -1279,7 +1275,6 @@ pub const Inst = struct {
12791275 .min,
12801276 .c_import,
12811277 .@"resume",
1282 .@"await",
12831278 .ret_err_value_code,
12841279 .extended,
12851280 .ret_ptr,
......@@ -1526,7 +1521,6 @@ pub const Inst = struct {
15261521 .tag_name,
15271522 .type_name,
15281523 .frame_type,
1529 .frame_size,
15301524 .int_from_float,
15311525 .float_from_int,
15321526 .ptr_from_int,
......@@ -1560,7 +1554,6 @@ pub const Inst = struct {
15601554 .min,
15611555 .c_import,
15621556 .@"resume",
1563 .@"await",
15641557 .ret_err_value_code,
15651558 .@"break",
15661559 .break_inline,
......@@ -1791,7 +1784,6 @@ pub const Inst = struct {
17911784 .tag_name = .un_node,
17921785 .type_name = .un_node,
17931786 .frame_type = .un_node,
1794 .frame_size = .un_node,
17951787
17961788 .int_from_float = .pl_node,
17971789 .float_from_int = .pl_node,
......@@ -1852,7 +1844,6 @@ pub const Inst = struct {
18521844 .make_ptr_const = .un_node,
18531845
18541846 .@"resume" = .un_node,
1855 .@"await" = .un_node,
18561847
18571848 .@"defer" = .@"defer",
18581849 .defer_err_code = .defer_err_code,
......@@ -2016,8 +2007,6 @@ pub const Inst = struct {
20162007 /// Implements the `@errorCast` builtin.
20172008 /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.
20182009 error_cast,
2019 /// `operand` is payload index to `UnNode`.
2020 await_nosuspend,
20212010 /// Implements `@breakpoint`.
20222011 /// `operand` is `src_node: Ast.Node.Offset`.
20232012 breakpoint,
......@@ -2038,9 +2027,6 @@ pub const Inst = struct {
20382027 /// `operand` is payload index to `Reify`.
20392028 /// `small` contains `NameStrategy`.
20402029 reify,
2041 /// Implements the `@asyncCall` builtin.
2042 /// `operand` is payload index to `AsyncCall`.
2043 builtin_async_call,
20442030 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
20452031 /// `small` 0=>weak 1=>strong
20462032 /// `operand` is payload index to `Cmpxchg`.
......@@ -3771,14 +3757,6 @@ pub const Inst = struct {
37713757 b: Ref,
37723758 };
37733759
3774 pub const AsyncCall = struct {
3775 node: Ast.Node.Offset,
3776 frame_buffer: Ref,
3777 result_ptr: Ref,
3778 fn_ptr: Ref,
3779 args: Ref,
3780 };
3781
37823760 /// Trailing: inst: Index // for every body_len
37833761 pub const Param = struct {
37843762 /// Null-terminated string index.
......@@ -4297,7 +4275,6 @@ fn findTrackableInner(
42974275 .tag_name,
42984276 .type_name,
42994277 .frame_type,
4300 .frame_size,
43014278 .int_from_float,
43024279 .float_from_int,
43034280 .ptr_from_int,
......@@ -4337,7 +4314,6 @@ fn findTrackableInner(
43374314 .resolve_inferred_alloc,
43384315 .make_ptr_const,
43394316 .@"resume",
4340 .@"await",
43414317 .save_err_ret_index,
43424318 .restore_err_ret_index_unconditional,
43434319 .restore_err_ret_index_fn_entry,
......@@ -4380,14 +4356,12 @@ fn findTrackableInner(
43804356 .prefetch,
43814357 .set_float_mode,
43824358 .error_cast,
4383 .await_nosuspend,
43844359 .breakpoint,
43854360 .disable_instrumentation,
43864361 .disable_intrinsics,
43874362 .select,
43884363 .int_from_error,
43894364 .error_from_int,
4390 .builtin_async_call,
43914365 .cmpxchg,
43924366 .c_va_arg,
43934367 .c_va_copy,
lib/std/zig/ZonGen.zig-5
......@@ -204,12 +204,8 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
204204
205205 .call_one,
206206 .call_one_comma,
207 .async_call_one,
208 .async_call_one_comma,
209207 .call,
210208 .call_comma,
211 .async_call,
212 .async_call_comma,
213209 .@"return",
214210 .if_simple,
215211 .@"if",
......@@ -226,7 +222,6 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
226222 .switch_comma,
227223 .@"nosuspend",
228224 .@"suspend",
229 .@"await",
230225 .@"resume",
231226 .@"try",
232227 .unreachable_literal,
lib/std/zig/parser_test.zig-76
......@@ -341,15 +341,6 @@ test "zig fmt: nosuspend block" {
341341 );
342342}
343343
344test "zig fmt: nosuspend await" {
345 try testCanonical(
346 \\fn foo() void {
347 \\ x = nosuspend await y;
348 \\}
349 \\
350 );
351}
352
353344test "zig fmt: container declaration, single line" {
354345 try testCanonical(
355346 \\const X = struct { foo: i32 };
......@@ -1093,18 +1084,6 @@ test "zig fmt: block in slice expression" {
10931084 );
10941085}
10951086
1096test "zig fmt: async function" {
1097 try testCanonical(
1098 \\pub const Server = struct {
1099 \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.@"async") void,
1100 \\};
1101 \\test "hi" {
1102 \\ var ptr: fn (i32) callconv(.@"async") void = @ptrCast(other);
1103 \\}
1104 \\
1105 );
1106}
1107
11081087test "zig fmt: whitespace fixes" {
11091088 try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",
11101089 \\test "" {
......@@ -1549,17 +1528,6 @@ test "zig fmt: spaces around slice operator" {
15491528 );
15501529}
15511530
1552test "zig fmt: async call in if condition" {
1553 try testCanonical(
1554 \\comptime {
1555 \\ if (async b()) {
1556 \\ a();
1557 \\ }
1558 \\}
1559 \\
1560 );
1561}
1562
15631531test "zig fmt: 2nd arg multiline string" {
15641532 try testCanonical(
15651533 \\comptime {
......@@ -3946,27 +3914,6 @@ test "zig fmt: inline asm" {
39463914 );
39473915}
39483916
3949test "zig fmt: async functions" {
3950 try testCanonical(
3951 \\fn simpleAsyncFn() void {
3952 \\ const a = async a.b();
3953 \\ x += 1;
3954 \\ suspend {}
3955 \\ x += 1;
3956 \\ suspend {}
3957 \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
3958 \\ await p;
3959 \\}
3960 \\
3961 \\test "suspend, resume, await" {
3962 \\ const p: anyframe = async testAsyncSeq();
3963 \\ resume p;
3964 \\ await p;
3965 \\}
3966 \\
3967 );
3968}
3969
39703917test "zig fmt: nosuspend" {
39713918 try testCanonical(
39723919 \\const a = nosuspend foo();
......@@ -6181,29 +6128,6 @@ test "recovery: missing return type" {
61816128 });
61826129}
61836130
6184test "recovery: continue after invalid decl" {
6185 try testError(
6186 \\fn foo {
6187 \\ inline;
6188 \\}
6189 \\pub test "" {
6190 \\ async a & b;
6191 \\}
6192 , &[_]Error{
6193 .expected_token,
6194 .expected_pub_item,
6195 .expected_param_list,
6196 });
6197 try testError(
6198 \\threadlocal test "" {
6199 \\ @a & b;
6200 \\}
6201 , &[_]Error{
6202 .expected_var_decl,
6203 .expected_param_list,
6204 });
6205}
6206
62076131test "recovery: invalid extern/inline" {
62086132 try testError(
62096133 \\inline test "" { a & b; }
lib/std/zig/render.zig-8
......@@ -591,7 +591,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
591591
592592 .@"try",
593593 .@"resume",
594 .@"await",
595594 => {
596595 try renderToken(r, tree.nodeMainToken(node), .space);
597596 return renderExpression(r, tree.nodeData(node).node, space);
......@@ -635,12 +634,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
635634
636635 .call_one,
637636 .call_one_comma,
638 .async_call_one,
639 .async_call_one_comma,
640637 .call,
641638 .call_comma,
642 .async_call,
643 .async_call_comma,
644639 => {
645640 var buf: [1]Ast.Node.Index = undefined;
646641 return renderCall(r, tree.fullCall(&buf, node).?, space);
......@@ -2551,9 +2546,6 @@ fn renderCall(
25512546 call: Ast.full.Call,
25522547 space: Space,
25532548) Error!void {
2554 if (call.async_token) |async_token| {
2555 try renderToken(r, async_token, .space);
2556 }
25572549 try renderExpression(r, call.ast.fn_expr, .none);
25582550 try renderParamList(r, call.ast.lparen, call.ast.params, space);
25592551}
lib/std/zig/tokenizer.zig-6
......@@ -17,8 +17,6 @@ pub const Token = struct {
1717 .{ "anyframe", .keyword_anyframe },
1818 .{ "anytype", .keyword_anytype },
1919 .{ "asm", .keyword_asm },
20 .{ "async", .keyword_async },
21 .{ "await", .keyword_await },
2220 .{ "break", .keyword_break },
2321 .{ "callconv", .keyword_callconv },
2422 .{ "catch", .keyword_catch },
......@@ -146,8 +144,6 @@ pub const Token = struct {
146144 keyword_anyframe,
147145 keyword_anytype,
148146 keyword_asm,
149 keyword_async,
150 keyword_await,
151147 keyword_break,
152148 keyword_callconv,
153149 keyword_catch,
......@@ -273,8 +269,6 @@ pub const Token = struct {
273269 .keyword_anyframe => "anyframe",
274270 .keyword_anytype => "anytype",
275271 .keyword_asm => "asm",
276 .keyword_async => "async",
277 .keyword_await => "await",
278272 .keyword_break => "break",
279273 .keyword_callconv => "callconv",
280274 .keyword_catch => "catch",
src/Sema.zig+3-54
......@@ -1280,7 +1280,6 @@ fn analyzeBodyInner(
12801280 .tag_name => try sema.zirTagName(block, inst),
12811281 .type_name => try sema.zirTypeName(block, inst),
12821282 .frame_type => try sema.zirFrameType(block, inst),
1283 .frame_size => try sema.zirFrameSize(block, inst),
12841283 .int_from_float => try sema.zirIntFromFloat(block, inst),
12851284 .float_from_int => try sema.zirFloatFromInt(block, inst),
12861285 .ptr_from_int => try sema.zirPtrFromInt(block, inst),
......@@ -1302,7 +1301,6 @@ fn analyzeBodyInner(
13021301 .mul_add => try sema.zirMulAdd(block, inst),
13031302 .builtin_call => try sema.zirBuiltinCall(block, inst),
13041303 .@"resume" => try sema.zirResume(block, inst),
1305 .@"await" => try sema.zirAwait(block, inst),
13061304 .for_len => try sema.zirForLen(block, inst),
13071305 .validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst),
13081306 .opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst),
......@@ -1410,12 +1408,10 @@ fn analyzeBodyInner(
14101408 .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended),
14111409 .prefetch => try sema.zirPrefetch( block, extended),
14121410 .error_cast => try sema.zirErrorCast( block, extended),
1413 .await_nosuspend => try sema.zirAwaitNosuspend( block, extended),
14141411 .select => try sema.zirSelect( block, extended),
14151412 .int_from_error => try sema.zirIntFromError( block, extended),
14161413 .error_from_int => try sema.zirErrorFromInt( block, extended),
14171414 .reify => try sema.zirReify( block, extended, inst),
1418 .builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended),
14191415 .cmpxchg => try sema.zirCmpxchg( block, extended),
14201416 .c_va_arg => try sema.zirCVaArg( block, extended),
14211417 .c_va_copy => try sema.zirCVaCopy( block, extended),
......@@ -7653,10 +7649,6 @@ fn analyzeCall(
76537649 const ip = &zcu.intern_pool;
76547650 const arena = sema.arena;
76557651
7656 if (modifier == .async_kw) {
7657 return sema.failWithUseOfAsync(block, call_src);
7658 }
7659
76607652 const maybe_func_inst = try sema.funcDeclSrcInst(callee);
76617653 const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{
76627654 .base_node_inst = fn_decl_inst,
......@@ -8048,14 +8040,13 @@ fn analyzeCall(
80488040 }
80498041
80508042 const call_tag: Air.Inst.Tag = switch (modifier) {
8051 .auto, .no_async => .call,
8043 .auto, .no_suspend => .call,
80528044 .never_tail => .call_never_tail,
80538045 .never_inline => .call_never_inline,
80548046 .always_tail => .call_always_tail,
80558047
80568048 .always_inline,
80578049 .compile_time,
8058 .async_kw,
80598050 => unreachable,
80608051 };
80618052
......@@ -22133,12 +22124,6 @@ fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2213322124 return sema.failWithUseOfAsync(block, src);
2213422125}
2213522126
22136fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
22137 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
22138 const src = block.nodeOffset(inst_data.src_node);
22139 return sema.failWithUseOfAsync(block, src);
22140}
22141
2214222127fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
2214322128 const pt = sema.pt;
2214422129 const zcu = pt.zcu;
......@@ -24776,14 +24761,14 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2477624761 var modifier = try sema.interpretBuiltinType(block, modifier_src, modifier_val, std.builtin.CallModifier);
2477724762 switch (modifier) {
2477824763 // These can be upgraded to comptime or nosuspend calls.
24779 .auto, .never_tail, .no_async => {
24764 .auto, .never_tail, .no_suspend => {
2478024765 if (block.isComptime()) {
2478124766 if (modifier == .never_tail) {
2478224767 return sema.fail(block, modifier_src, "unable to perform 'never_tail' call at compile-time", .{});
2478324768 }
2478424769 modifier = .compile_time;
2478524770 } else if (extra.flags.is_nosuspend) {
24786 modifier = .no_async;
24771 modifier = .no_suspend;
2478724772 }
2478824773 },
2478924774 // These can be upgraded to comptime. nosuspend bit can be safely ignored.
......@@ -24801,14 +24786,6 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2480124786 modifier = .compile_time;
2480224787 }
2480324788 },
24804 .async_kw => {
24805 if (extra.flags.is_nosuspend) {
24806 return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{});
24807 }
24808 if (block.isComptime()) {
24809 return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{});
24810 }
24811 },
2481224789 .never_inline => {
2481324790 if (block.isComptime()) {
2481424791 return sema.fail(block, modifier_src, "unable to perform 'never_inline' call at compile-time", .{});
......@@ -25797,40 +25774,12 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2579725774 });
2579825775}
2579925776
25800fn zirBuiltinAsyncCall(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
25801 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
25802 const src = block.nodeOffset(extra.node);
25803 return sema.failWithUseOfAsync(block, src);
25804}
25805
2580625777fn zirResume(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
2580725778 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2580825779 const src = block.nodeOffset(inst_data.src_node);
2580925780 return sema.failWithUseOfAsync(block, src);
2581025781}
2581125782
25812fn zirAwait(
25813 sema: *Sema,
25814 block: *Block,
25815 inst: Zir.Inst.Index,
25816) CompileError!Air.Inst.Ref {
25817 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
25818 const src = block.nodeOffset(inst_data.src_node);
25819
25820 return sema.failWithUseOfAsync(block, src);
25821}
25822
25823fn zirAwaitNosuspend(
25824 sema: *Sema,
25825 block: *Block,
25826 extended: Zir.Inst.Extended.InstData,
25827) CompileError!Air.Inst.Ref {
25828 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
25829 const src = block.nodeOffset(extra.node);
25830
25831 return sema.failWithUseOfAsync(block, src);
25832}
25833
2583425783fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
2583525784 const tracy = trace(@src());
2583625785 defer tracy.end();
src/Zcu.zig-4
......@@ -1443,12 +1443,8 @@ pub const SrcLoc = struct {
14431443 .field_access => tree.nodeData(node).node_and_token[1],
14441444 .call_one,
14451445 .call_one_comma,
1446 .async_call_one,
1447 .async_call_one_comma,
14481446 .call,
14491447 .call_comma,
1450 .async_call,
1451 .async_call_comma,
14521448 => blk: {
14531449 const full = tree.fullCall(&buf, node).?;
14541450 break :blk tree.lastToken(full.ast.fn_expr);
src/codegen/llvm.zig+2-2
......@@ -5273,7 +5273,7 @@ pub const FuncGen = struct {
52735273 switch (modifier) {
52745274 .auto, .always_tail => {},
52755275 .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),
5276 .async_kw, .no_async, .always_inline, .compile_time => unreachable,
5276 .no_suspend, .always_inline, .compile_time => unreachable,
52775277 }
52785278
52795279 const ret_ptr = if (!sret) null else blk: {
......@@ -5488,7 +5488,7 @@ pub const FuncGen = struct {
54885488 .auto, .never_inline => .normal,
54895489 .never_tail => .notail,
54905490 .always_tail => .musttail,
5491 .async_kw, .no_async, .always_inline, .compile_time => unreachable,
5491 .no_suspend, .always_inline, .compile_time => unreachable,
54925492 },
54935493 toLlvmCallConvTag(fn_info.cc, target).?,
54945494 try attributes.finish(&o.builder),
src/print_zir.zig-17
......@@ -261,14 +261,12 @@ const Writer = struct {
261261 .tag_name,
262262 .type_name,
263263 .frame_type,
264 .frame_size,
265264 .clz,
266265 .ctz,
267266 .pop_count,
268267 .byte_swap,
269268 .bit_reverse,
270269 .@"resume",
271 .@"await",
272270 .make_ptr_const,
273271 .validate_deref,
274272 .validate_const,
......@@ -565,7 +563,6 @@ const Writer = struct {
565563
566564 .tuple_decl => try self.writeTupleDecl(stream, extended),
567565
568 .await_nosuspend,
569566 .c_undef,
570567 .c_include,
571568 .set_float_mode,
......@@ -611,7 +608,6 @@ const Writer = struct {
611608 try self.writeSrcNode(stream, inst_data.node);
612609 },
613610
614 .builtin_async_call => try self.writeBuiltinAsyncCall(stream, extended),
615611 .cmpxchg => try self.writeCmpxchg(stream, extended),
616612 .ptr_cast_full => try self.writePtrCastFull(stream, extended),
617613 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
......@@ -932,19 +928,6 @@ const Writer = struct {
932928 try self.writeSrcNode(stream, extra.src_node);
933929 }
934930
935 fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
936 const extra = self.code.extraData(Zir.Inst.AsyncCall, extended.operand).data;
937 try self.writeInstRef(stream, extra.frame_buffer);
938 try stream.writeAll(", ");
939 try self.writeInstRef(stream, extra.result_ptr);
940 try stream.writeAll(", ");
941 try self.writeInstRef(stream, extra.fn_ptr);
942 try stream.writeAll(", ");
943 try self.writeInstRef(stream, extra.args);
944 try stream.writeAll(") ");
945 try self.writeSrcNode(stream, extra.node);
946 }
947
948931 fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
949932 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
950933 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
test/behavior.zig-2
......@@ -5,9 +5,7 @@ test {
55 _ = @import("behavior/align.zig");
66 _ = @import("behavior/alignof.zig");
77 _ = @import("behavior/array.zig");
8 _ = @import("behavior/async_fn.zig");
98 _ = @import("behavior/atomics.zig");
10 _ = @import("behavior/await_struct.zig");
119 _ = @import("behavior/basic.zig");
1210 _ = @import("behavior/bit_shifting.zig");
1311 _ = @import("behavior/bitcast.zig");
test/behavior/align.zig-24
......@@ -425,30 +425,6 @@ test "struct field explicit alignment" {
425425 try expect(@intFromPtr(&node.massive_byte) % 64 == 0);
426426}
427427
428test "align(@alignOf(T)) T does not force resolution of T" {
429 if (true) return error.SkipZigTest; // TODO
430
431 const S = struct {
432 const A = struct {
433 a: *align(@alignOf(A)) A,
434 };
435 fn doTheTest() void {
436 suspend {
437 resume @frame();
438 }
439 _ = bar(@Frame(doTheTest));
440 }
441 fn bar(comptime T: type) *align(@alignOf(T)) T {
442 ok = true;
443 return undefined;
444 }
445
446 var ok = false;
447 };
448 _ = async S.doTheTest();
449 try expect(S.ok);
450}
451
452428test "align(N) on functions" {
453429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
454430 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/async_fn.zig deleted-1911
......@@ -1,1911 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;
6const expectEqualStrings = std.testing.expectEqualStrings;
7const expectError = std.testing.expectError;
8
9var global_x: i32 = 1;
10
11test "simple coroutine suspend and resume" {
12 if (true) return error.SkipZigTest; // TODO
13 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
14
15 var frame = async simpleAsyncFn();
16 try expect(global_x == 2);
17 resume frame;
18 try expect(global_x == 3);
19 const af: anyframe->void = &frame;
20 _ = af;
21 resume frame;
22 try expect(global_x == 4);
23}
24fn simpleAsyncFn() void {
25 global_x += 1;
26 suspend {}
27 global_x += 1;
28 suspend {}
29 global_x += 1;
30}
31
32var global_y: i32 = 1;
33
34test "pass parameter to coroutine" {
35 if (true) return error.SkipZigTest; // TODO
36 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
37
38 var p = async simpleAsyncFnWithArg(2);
39 try expect(global_y == 3);
40 resume p;
41 try expect(global_y == 5);
42}
43fn simpleAsyncFnWithArg(delta: i32) void {
44 global_y += delta;
45 suspend {}
46 global_y += delta;
47}
48
49test "suspend at end of function" {
50 if (true) return error.SkipZigTest; // TODO
51 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
52
53 const S = struct {
54 var x: i32 = 1;
55
56 fn doTheTest() !void {
57 try expect(x == 1);
58 const p = async suspendAtEnd();
59 _ = p;
60 try expect(x == 2);
61 }
62
63 fn suspendAtEnd() void {
64 x += 1;
65 suspend {}
66 }
67 };
68 try S.doTheTest();
69}
70
71test "local variable in async function" {
72 if (true) return error.SkipZigTest; // TODO
73 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
74
75 const S = struct {
76 var x: i32 = 0;
77
78 fn doTheTest() !void {
79 try expect(x == 0);
80 var p = async add(1, 2);
81 try expect(x == 0);
82 resume p;
83 try expect(x == 0);
84 resume p;
85 try expect(x == 0);
86 resume p;
87 try expect(x == 3);
88 }
89
90 fn add(a: i32, b: i32) void {
91 var accum: i32 = 0;
92 suspend {}
93 accum += a;
94 suspend {}
95 accum += b;
96 suspend {}
97 x = accum;
98 }
99 };
100 try S.doTheTest();
101}
102
103test "calling an inferred async function" {
104 if (true) return error.SkipZigTest; // TODO
105 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
106
107 const S = struct {
108 var x: i32 = 1;
109 var other_frame: *@Frame(other) = undefined;
110
111 fn doTheTest() !void {
112 _ = async first();
113 try expect(x == 1);
114 resume other_frame.*;
115 try expect(x == 2);
116 }
117
118 fn first() void {
119 other();
120 }
121 fn other() void {
122 other_frame = @frame();
123 suspend {}
124 x += 1;
125 }
126 };
127 try S.doTheTest();
128}
129
130test "@frameSize" {
131 if (true) return error.SkipZigTest; // TODO
132 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
133
134 if (builtin.target.cpu.arch == .thumb or builtin.target.cpu.arch == .thumbeb)
135 return error.SkipZigTest;
136
137 const S = struct {
138 fn doTheTest() !void {
139 {
140 var ptr = @as(fn (i32) callconv(.@"async") void, @ptrCast(other));
141 _ = &ptr;
142 const size = @frameSize(ptr);
143 try expect(size == @sizeOf(@Frame(other)));
144 }
145 {
146 var ptr = @as(fn () callconv(.@"async") void, @ptrCast(first));
147 _ = &ptr;
148 const size = @frameSize(ptr);
149 try expect(size == @sizeOf(@Frame(first)));
150 }
151 }
152
153 fn first() void {
154 other(1);
155 }
156 fn other(param: i32) void {
157 _ = param;
158 var local: i32 = undefined;
159 _ = &local;
160 suspend {}
161 }
162 };
163 try S.doTheTest();
164}
165
166test "coroutine suspend, resume" {
167 if (true) return error.SkipZigTest; // TODO
168 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
169
170 const S = struct {
171 var frame: anyframe = undefined;
172
173 fn doTheTest() !void {
174 _ = async amain();
175 seq('d');
176 resume frame;
177 seq('h');
178
179 try expect(std.mem.eql(u8, &points, "abcdefgh"));
180 }
181
182 fn amain() void {
183 seq('a');
184 var f = async testAsyncSeq();
185 seq('c');
186 await f;
187 seq('g');
188 }
189
190 fn testAsyncSeq() void {
191 defer seq('f');
192
193 seq('b');
194 suspend {
195 frame = @frame();
196 }
197 seq('e');
198 }
199 var points = [_]u8{'x'} ** "abcdefgh".len;
200 var index: usize = 0;
201
202 fn seq(c: u8) void {
203 points[index] = c;
204 index += 1;
205 }
206 };
207 try S.doTheTest();
208}
209
210test "coroutine suspend with block" {
211 if (true) return error.SkipZigTest; // TODO
212 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
213
214 const p = async testSuspendBlock();
215 _ = p;
216 try expect(!global_result);
217 resume a_promise;
218 try expect(global_result);
219}
220
221var a_promise: anyframe = undefined;
222var global_result = false;
223fn testSuspendBlock() callconv(.@"async") void {
224 suspend {
225 comptime assert(@TypeOf(@frame()) == *@Frame(testSuspendBlock)) catch unreachable;
226 a_promise = @frame();
227 }
228
229 // Test to make sure that @frame() works as advertised (issue #1296)
230 // var our_handle: anyframe = @frame();
231 expect(a_promise == @as(anyframe, @frame())) catch @panic("test failed");
232
233 global_result = true;
234}
235
236var await_a_promise: anyframe = undefined;
237var await_final_result: i32 = 0;
238
239test "coroutine await" {
240 if (true) return error.SkipZigTest; // TODO
241 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
242
243 await_seq('a');
244 var p = async await_amain();
245 _ = &p;
246 await_seq('f');
247 resume await_a_promise;
248 await_seq('i');
249 try expect(await_final_result == 1234);
250 try expect(std.mem.eql(u8, &await_points, "abcdefghi"));
251}
252fn await_amain() callconv(.@"async") void {
253 await_seq('b');
254 var p = async await_another();
255 await_seq('e');
256 await_final_result = await p;
257 await_seq('h');
258}
259fn await_another() callconv(.@"async") i32 {
260 await_seq('c');
261 suspend {
262 await_seq('d');
263 await_a_promise = @frame();
264 }
265 await_seq('g');
266 return 1234;
267}
268
269var await_points = [_]u8{0} ** "abcdefghi".len;
270var await_seq_index: usize = 0;
271
272fn await_seq(c: u8) void {
273 await_points[await_seq_index] = c;
274 await_seq_index += 1;
275}
276
277var early_final_result: i32 = 0;
278
279test "coroutine await early return" {
280 if (true) return error.SkipZigTest; // TODO
281 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
282
283 early_seq('a');
284 var p = async early_amain();
285 _ = &p;
286 early_seq('f');
287 try expect(early_final_result == 1234);
288 try expect(std.mem.eql(u8, &early_points, "abcdef"));
289}
290fn early_amain() callconv(.@"async") void {
291 early_seq('b');
292 var p = async early_another();
293 early_seq('d');
294 early_final_result = await p;
295 early_seq('e');
296}
297fn early_another() callconv(.@"async") i32 {
298 early_seq('c');
299 return 1234;
300}
301
302var early_points = [_]u8{0} ** "abcdef".len;
303var early_seq_index: usize = 0;
304
305fn early_seq(c: u8) void {
306 early_points[early_seq_index] = c;
307 early_seq_index += 1;
308}
309
310test "async function with dot syntax" {
311 if (true) return error.SkipZigTest; // TODO
312 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
313
314 const S = struct {
315 var y: i32 = 1;
316 fn foo() callconv(.@"async") void {
317 y += 1;
318 suspend {}
319 }
320 };
321 const p = async S.foo();
322 _ = p;
323 try expect(S.y == 2);
324}
325
326test "async fn pointer in a struct field" {
327 if (true) return error.SkipZigTest; // TODO
328 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
329
330 var data: i32 = 1;
331 const Foo = struct {
332 bar: fn (*i32) callconv(.@"async") void,
333 };
334 var foo = Foo{ .bar = simpleAsyncFn2 };
335 _ = &foo;
336 var bytes: [64]u8 align(16) = undefined;
337 const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
338 comptime assert(@TypeOf(f) == anyframe->void);
339 try expect(data == 2);
340 resume f;
341 try expect(data == 4);
342 _ = async doTheAwait(f);
343 try expect(data == 4);
344}
345
346fn doTheAwait(f: anyframe->void) void {
347 await f;
348}
349fn simpleAsyncFn2(y: *i32) callconv(.@"async") void {
350 defer y.* += 2;
351 y.* += 1;
352 suspend {}
353}
354
355test "@asyncCall with return type" {
356 if (true) return error.SkipZigTest; // TODO
357 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
358
359 const Foo = struct {
360 bar: fn () callconv(.@"async") i32,
361
362 var global_frame: anyframe = undefined;
363 fn middle() callconv(.@"async") i32 {
364 return afunc();
365 }
366
367 fn afunc() i32 {
368 global_frame = @frame();
369 suspend {}
370 return 1234;
371 }
372 };
373 var foo = Foo{ .bar = Foo.middle };
374 _ = &foo;
375 var bytes: [150]u8 align(16) = undefined;
376 var aresult: i32 = 0;
377 _ = @asyncCall(&bytes, &aresult, foo.bar, .{});
378 try expect(aresult == 0);
379 resume Foo.global_frame;
380 try expect(aresult == 1234);
381}
382
383test "async fn with inferred error set" {
384 if (true) return error.SkipZigTest; // TODO
385 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
386
387 const S = struct {
388 var global_frame: anyframe = undefined;
389
390 fn doTheTest() !void {
391 var frame: [1]@Frame(middle) = undefined;
392 var fn_ptr = middle;
393 _ = &fn_ptr;
394 var result: @typeInfo(@typeInfo(@TypeOf(fn_ptr)).@"fn".return_type.?).error_union.error_set!void = undefined;
395 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr, .{});
396 resume global_frame;
397 try std.testing.expectError(error.Fail, result);
398 }
399 fn middle() callconv(.@"async") !void {
400 var f = async middle2();
401 return await f;
402 }
403
404 fn middle2() !void {
405 return failing();
406 }
407
408 fn failing() !void {
409 global_frame = @frame();
410 suspend {}
411 return error.Fail;
412 }
413 };
414 try S.doTheTest();
415}
416
417test "error return trace across suspend points - early return" {
418 if (true) return error.SkipZigTest; // TODO
419 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
420
421 const p = nonFailing();
422 resume p;
423 const p2 = async printTrace(p);
424 _ = p2;
425}
426
427test "error return trace across suspend points - async return" {
428 if (true) return error.SkipZigTest; // TODO
429 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
430
431 const p = nonFailing();
432 const p2 = async printTrace(p);
433 _ = p2;
434 resume p;
435}
436
437fn nonFailing() (anyframe->anyerror!void) {
438 const Static = struct {
439 var frame: @Frame(suspendThenFail) = undefined;
440 };
441 Static.frame = async suspendThenFail();
442 return &Static.frame;
443}
444fn suspendThenFail() callconv(.@"async") anyerror!void {
445 suspend {}
446 return error.Fail;
447}
448fn printTrace(p: anyframe->(anyerror!void)) callconv(.@"async") void {
449 (await p) catch |e| {
450 std.testing.expect(e == error.Fail) catch @panic("test failure");
451 if (@errorReturnTrace()) |trace| {
452 expect(trace.index == 1) catch @panic("test failure");
453 } else switch (builtin.mode) {
454 .Debug, .ReleaseSafe => @panic("expected return trace"),
455 .ReleaseFast, .ReleaseSmall => {},
456 }
457 };
458}
459
460test "break from suspend" {
461 if (true) return error.SkipZigTest; // TODO
462 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
463
464 var my_result: i32 = 1;
465 const p = async testBreakFromSuspend(&my_result);
466 _ = p;
467 try std.testing.expect(my_result == 2);
468}
469fn testBreakFromSuspend(my_result: *i32) callconv(.@"async") void {
470 suspend {
471 resume @frame();
472 }
473 my_result.* += 1;
474 suspend {}
475 my_result.* += 1;
476}
477
478test "heap allocated async function frame" {
479 if (true) return error.SkipZigTest; // TODO
480 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
481
482 const S = struct {
483 var x: i32 = 42;
484
485 fn doTheTest() !void {
486 const frame = try std.testing.allocator.create(@Frame(someFunc));
487 defer std.testing.allocator.destroy(frame);
488
489 try expect(x == 42);
490 frame.* = async someFunc();
491 try expect(x == 43);
492 resume frame;
493 try expect(x == 44);
494 }
495
496 fn someFunc() void {
497 x += 1;
498 suspend {}
499 x += 1;
500 }
501 };
502 try S.doTheTest();
503}
504
505test "async function call return value" {
506 if (true) return error.SkipZigTest; // TODO
507 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
508
509 const S = struct {
510 var frame: anyframe = undefined;
511 var pt = Point{ .x = 10, .y = 11 };
512
513 fn doTheTest() !void {
514 try expectEqual(pt.x, 10);
515 try expectEqual(pt.y, 11);
516 _ = async first();
517 try expectEqual(pt.x, 10);
518 try expectEqual(pt.y, 11);
519 resume frame;
520 try expectEqual(pt.x, 1);
521 try expectEqual(pt.y, 2);
522 }
523
524 fn first() void {
525 pt = second(1, 2);
526 }
527
528 fn second(x: i32, y: i32) Point {
529 return other(x, y);
530 }
531
532 fn other(x: i32, y: i32) Point {
533 frame = @frame();
534 suspend {}
535 return Point{
536 .x = x,
537 .y = y,
538 };
539 }
540
541 const Point = struct {
542 x: i32,
543 y: i32,
544 };
545 };
546 try S.doTheTest();
547}
548
549test "suspension points inside branching control flow" {
550 if (true) return error.SkipZigTest; // TODO
551 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
552
553 const S = struct {
554 var result: i32 = 10;
555
556 fn doTheTest() !void {
557 try expect(10 == result);
558 var frame = async func(true);
559 try expect(10 == result);
560 resume frame;
561 try expect(11 == result);
562 resume frame;
563 try expect(12 == result);
564 resume frame;
565 try expect(13 == result);
566 }
567
568 fn func(b: bool) void {
569 while (b) {
570 suspend {}
571 result += 1;
572 }
573 }
574 };
575 try S.doTheTest();
576}
577
578test "call async function which has struct return type" {
579 if (true) return error.SkipZigTest; // TODO
580 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
581
582 const S = struct {
583 var frame: anyframe = undefined;
584
585 fn doTheTest() void {
586 _ = async atest();
587 resume frame;
588 }
589
590 fn atest() void {
591 const result = func();
592 expect(result.x == 5) catch @panic("test failed");
593 expect(result.y == 6) catch @panic("test failed");
594 }
595
596 const Point = struct {
597 x: usize,
598 y: usize,
599 };
600
601 fn func() Point {
602 suspend {
603 frame = @frame();
604 }
605 return Point{
606 .x = 5,
607 .y = 6,
608 };
609 }
610 };
611 S.doTheTest();
612}
613
614test "pass string literal to async function" {
615 if (true) return error.SkipZigTest; // TODO
616 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
617
618 const S = struct {
619 var frame: anyframe = undefined;
620 var ok: bool = false;
621
622 fn doTheTest() !void {
623 _ = async hello("hello");
624 resume frame;
625 try expect(ok);
626 }
627
628 fn hello(msg: []const u8) void {
629 frame = @frame();
630 suspend {}
631 expectEqualStrings("hello", msg) catch @panic("test failed");
632 ok = true;
633 }
634 };
635 try S.doTheTest();
636}
637
638test "await inside an errdefer" {
639 if (true) return error.SkipZigTest; // TODO
640 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
641
642 const S = struct {
643 var frame: anyframe = undefined;
644
645 fn doTheTest() !void {
646 _ = async amainWrap();
647 resume frame;
648 }
649
650 fn amainWrap() !void {
651 var foo = async func();
652 errdefer await foo;
653 return error.Bad;
654 }
655
656 fn func() void {
657 frame = @frame();
658 suspend {}
659 }
660 };
661 try S.doTheTest();
662}
663
664test "try in an async function with error union and non-zero-bit payload" {
665 if (true) return error.SkipZigTest; // TODO
666 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
667
668 const S = struct {
669 var frame: anyframe = undefined;
670 var ok = false;
671
672 fn doTheTest() !void {
673 _ = async amain();
674 resume frame;
675 try expect(ok);
676 }
677
678 fn amain() void {
679 std.testing.expectError(error.Bad, theProblem()) catch @panic("test failed");
680 ok = true;
681 }
682
683 fn theProblem() ![]u8 {
684 frame = @frame();
685 suspend {}
686 const result = try other();
687 return result;
688 }
689
690 fn other() ![]u8 {
691 return error.Bad;
692 }
693 };
694 try S.doTheTest();
695}
696
697test "returning a const error from async function" {
698 if (true) return error.SkipZigTest; // TODO
699 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
700
701 const S = struct {
702 var frame: anyframe = undefined;
703 var ok = false;
704
705 fn doTheTest() !void {
706 _ = async amain();
707 resume frame;
708 try expect(ok);
709 }
710
711 fn amain() !void {
712 var download_frame = async fetchUrl(10, "a string");
713 const download_text = try await download_frame;
714 _ = download_text;
715
716 @panic("should not get here");
717 }
718
719 fn fetchUrl(unused: i32, url: []const u8) ![]u8 {
720 _ = unused;
721 _ = url;
722 frame = @frame();
723 suspend {}
724 ok = true;
725 return error.OutOfMemory;
726 }
727 };
728 try S.doTheTest();
729}
730
731test "async/await typical usage" {
732 if (true) return error.SkipZigTest; // TODO
733 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
734
735 inline for ([_]bool{ false, true }) |b1| {
736 inline for ([_]bool{ false, true }) |b2| {
737 inline for ([_]bool{ false, true }) |b3| {
738 inline for ([_]bool{ false, true }) |b4| {
739 testAsyncAwaitTypicalUsage(b1, b2, b3, b4).doTheTest();
740 }
741 }
742 }
743 }
744}
745
746fn testAsyncAwaitTypicalUsage(
747 comptime simulate_fail_download: bool,
748 comptime simulate_fail_file: bool,
749 comptime suspend_download: bool,
750 comptime suspend_file: bool,
751) type {
752 return struct {
753 fn doTheTest() void {
754 _ = async amainWrap();
755 if (suspend_file) {
756 resume global_file_frame;
757 }
758 if (suspend_download) {
759 resume global_download_frame;
760 }
761 }
762 fn amainWrap() void {
763 if (amain()) |_| {
764 expect(!simulate_fail_download) catch @panic("test failure");
765 expect(!simulate_fail_file) catch @panic("test failure");
766 } else |e| switch (e) {
767 error.NoResponse => expect(simulate_fail_download) catch @panic("test failure"),
768 error.FileNotFound => expect(simulate_fail_file) catch @panic("test failure"),
769 else => @panic("test failure"),
770 }
771 }
772
773 fn amain() !void {
774 const allocator = std.testing.allocator;
775 var download_frame = async fetchUrl(allocator, "https://example.com/");
776 var download_awaited = false;
777 errdefer if (!download_awaited) {
778 if (await download_frame) |x| allocator.free(x) else |_| {}
779 };
780
781 var file_frame = async readFile(allocator, "something.txt");
782 var file_awaited = false;
783 errdefer if (!file_awaited) {
784 if (await file_frame) |x| allocator.free(x) else |_| {}
785 };
786
787 download_awaited = true;
788 const download_text = try await download_frame;
789 defer allocator.free(download_text);
790
791 file_awaited = true;
792 const file_text = try await file_frame;
793 defer allocator.free(file_text);
794
795 try expect(std.mem.eql(u8, "expected download text", download_text));
796 try expect(std.mem.eql(u8, "expected file text", file_text));
797 }
798
799 var global_download_frame: anyframe = undefined;
800 fn fetchUrl(allocator: std.mem.Allocator, url: []const u8) anyerror![]u8 {
801 _ = url;
802 const result = try allocator.dupe(u8, "expected download text");
803 errdefer allocator.free(result);
804 if (suspend_download) {
805 suspend {
806 global_download_frame = @frame();
807 }
808 }
809 if (simulate_fail_download) return error.NoResponse;
810 return result;
811 }
812
813 var global_file_frame: anyframe = undefined;
814 fn readFile(allocator: std.mem.Allocator, filename: []const u8) anyerror![]u8 {
815 _ = filename;
816 const result = try allocator.dupe(u8, "expected file text");
817 errdefer allocator.free(result);
818 if (suspend_file) {
819 suspend {
820 global_file_frame = @frame();
821 }
822 }
823 if (simulate_fail_file) return error.FileNotFound;
824 return result;
825 }
826 };
827}
828
829test "alignment of local variables in async functions" {
830 if (true) return error.SkipZigTest; // TODO
831 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
832
833 const S = struct {
834 fn doTheTest() !void {
835 var y: u8 = 123;
836 _ = &y;
837 var x: u8 align(128) = 1;
838 try expect(@intFromPtr(&x) % 128 == 0);
839 }
840 };
841 try S.doTheTest();
842}
843
844test "no reason to resolve frame still works" {
845 if (true) return error.SkipZigTest; // TODO
846 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
847
848 _ = async simpleNothing();
849}
850fn simpleNothing() void {
851 var x: i32 = 1234;
852 _ = &x;
853}
854
855test "async call a generic function" {
856 if (true) return error.SkipZigTest; // TODO
857 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
858
859 const S = struct {
860 fn doTheTest() !void {
861 var f = async func(i32, 2);
862 const result = await f;
863 try expect(result == 3);
864 }
865
866 fn func(comptime T: type, inc: T) T {
867 var x: T = 1;
868 suspend {
869 resume @frame();
870 }
871 x += inc;
872 return x;
873 }
874 };
875 _ = async S.doTheTest();
876}
877
878test "return from suspend block" {
879 if (true) return error.SkipZigTest; // TODO
880 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
881
882 const S = struct {
883 fn doTheTest() !void {
884 expect(func() == 1234) catch @panic("test failure");
885 }
886 fn func() i32 {
887 suspend {
888 return 1234;
889 }
890 }
891 };
892 _ = async S.doTheTest();
893}
894
895test "struct parameter to async function is copied to the frame" {
896 if (true) return error.SkipZigTest; // TODO
897 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
898
899 const S = struct {
900 const Point = struct {
901 x: i32,
902 y: i32,
903 };
904
905 var frame: anyframe = undefined;
906
907 fn doTheTest() void {
908 _ = async atest();
909 resume frame;
910 }
911
912 fn atest() void {
913 var f: @Frame(foo) = undefined;
914 bar(&f);
915 clobberStack(10);
916 }
917
918 fn clobberStack(x: i32) void {
919 if (x == 0) return;
920 clobberStack(x - 1);
921 var y: i32 = x;
922 _ = &y;
923 }
924
925 fn bar(f: *@Frame(foo)) void {
926 var pt = Point{ .x = 1, .y = 2 };
927 _ = &pt;
928 f.* = async foo(pt);
929 const result = await f;
930 expect(result == 1) catch @panic("test failure");
931 }
932
933 fn foo(point: Point) i32 {
934 suspend {
935 frame = @frame();
936 }
937 return point.x;
938 }
939 };
940 S.doTheTest();
941}
942
943test "cast fn to async fn when it is inferred to be async" {
944 if (true) return error.SkipZigTest; // TODO
945 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
946
947 const S = struct {
948 var frame: anyframe = undefined;
949 var ok = false;
950
951 fn doTheTest() void {
952 var ptr: fn () callconv(.@"async") i32 = undefined;
953 ptr = func;
954 var buf: [100]u8 align(16) = undefined;
955 var result: i32 = undefined;
956 const f = @asyncCall(&buf, &result, ptr, .{});
957 _ = await f;
958 expect(result == 1234) catch @panic("test failure");
959 ok = true;
960 }
961
962 fn func() i32 {
963 suspend {
964 frame = @frame();
965 }
966 return 1234;
967 }
968 };
969 _ = async S.doTheTest();
970 resume S.frame;
971 try expect(S.ok);
972}
973
974test "cast fn to async fn when it is inferred to be async, awaited directly" {
975 if (true) return error.SkipZigTest; // TODO
976 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
977
978 const S = struct {
979 var frame: anyframe = undefined;
980 var ok = false;
981
982 fn doTheTest() void {
983 var ptr: fn () callconv(.@"async") i32 = undefined;
984 ptr = func;
985 var buf: [100]u8 align(16) = undefined;
986 var result: i32 = undefined;
987 _ = await @asyncCall(&buf, &result, ptr, .{});
988 expect(result == 1234) catch @panic("test failure");
989 ok = true;
990 }
991
992 fn func() i32 {
993 suspend {
994 frame = @frame();
995 }
996 return 1234;
997 }
998 };
999 _ = async S.doTheTest();
1000 resume S.frame;
1001 try expect(S.ok);
1002}
1003
1004test "await does not force async if callee is blocking" {
1005 if (true) return error.SkipZigTest; // TODO
1006 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1007
1008 const S = struct {
1009 fn simple() i32 {
1010 return 1234;
1011 }
1012 };
1013 var x = async S.simple();
1014 try expect(await x == 1234);
1015}
1016
1017test "recursive async function" {
1018 if (true) return error.SkipZigTest; // TODO
1019 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1020
1021 try expect(recursiveAsyncFunctionTest(false).doTheTest() == 55);
1022 try expect(recursiveAsyncFunctionTest(true).doTheTest() == 55);
1023}
1024
1025fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type {
1026 return struct {
1027 fn fib(allocator: std.mem.Allocator, x: u32) error{OutOfMemory}!u32 {
1028 if (x <= 1) return x;
1029
1030 if (suspending_implementation) {
1031 suspend {
1032 resume @frame();
1033 }
1034 }
1035
1036 const f1 = try allocator.create(@Frame(fib));
1037 defer allocator.destroy(f1);
1038
1039 const f2 = try allocator.create(@Frame(fib));
1040 defer allocator.destroy(f2);
1041
1042 f1.* = async fib(allocator, x - 1);
1043 var f1_awaited = false;
1044 errdefer if (!f1_awaited) {
1045 _ = await f1;
1046 };
1047
1048 f2.* = async fib(allocator, x - 2);
1049 var f2_awaited = false;
1050 errdefer if (!f2_awaited) {
1051 _ = await f2;
1052 };
1053
1054 var sum: u32 = 0;
1055
1056 f1_awaited = true;
1057 sum += try await f1;
1058
1059 f2_awaited = true;
1060 sum += try await f2;
1061
1062 return sum;
1063 }
1064
1065 fn doTheTest() u32 {
1066 if (suspending_implementation) {
1067 var result: u32 = undefined;
1068 _ = async amain(&result);
1069 return result;
1070 } else {
1071 return fib(std.testing.allocator, 10) catch unreachable;
1072 }
1073 }
1074
1075 fn amain(result: *u32) void {
1076 var x = async fib(std.testing.allocator, 10);
1077 result.* = (await x) catch unreachable;
1078 }
1079 };
1080}
1081
1082test "@asyncCall with comptime-known function, but not awaited directly" {
1083 if (true) return error.SkipZigTest; // TODO
1084 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1085
1086 const S = struct {
1087 var global_frame: anyframe = undefined;
1088
1089 fn doTheTest() !void {
1090 var frame: [1]@Frame(middle) = undefined;
1091 var result: @typeInfo(@typeInfo(@TypeOf(middle)).@"fn".return_type.?).error_union.error_set!void = undefined;
1092 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle, .{});
1093 resume global_frame;
1094 try std.testing.expectError(error.Fail, result);
1095 }
1096 fn middle() callconv(.@"async") !void {
1097 var f = async middle2();
1098 return await f;
1099 }
1100
1101 fn middle2() !void {
1102 return failing();
1103 }
1104
1105 fn failing() !void {
1106 global_frame = @frame();
1107 suspend {}
1108 return error.Fail;
1109 }
1110 };
1111 try S.doTheTest();
1112}
1113
1114test "@asyncCall with actual frame instead of byte buffer" {
1115 if (true) return error.SkipZigTest; // TODO
1116 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1117
1118 const S = struct {
1119 fn func() i32 {
1120 suspend {}
1121 return 1234;
1122 }
1123 };
1124 var frame: @Frame(S.func) = undefined;
1125 var result: i32 = undefined;
1126 const ptr = @asyncCall(&frame, &result, S.func, .{});
1127 resume ptr;
1128 try expect(result == 1234);
1129}
1130
1131test "@asyncCall using the result location inside the frame" {
1132 if (true) return error.SkipZigTest; // TODO
1133 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1134
1135 const S = struct {
1136 fn simple2(y: *i32) callconv(.@"async") i32 {
1137 defer y.* += 2;
1138 y.* += 1;
1139 suspend {}
1140 return 1234;
1141 }
1142 fn getAnswer(f: anyframe->i32, out: *i32) void {
1143 out.* = await f;
1144 }
1145 };
1146 var data: i32 = 1;
1147 const Foo = struct {
1148 bar: fn (*i32) callconv(.@"async") i32,
1149 };
1150 var foo = Foo{ .bar = S.simple2 };
1151 _ = &foo;
1152 var bytes: [64]u8 align(16) = undefined;
1153 const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
1154 comptime assert(@TypeOf(f) == anyframe->i32);
1155 try expect(data == 2);
1156 resume f;
1157 try expect(data == 4);
1158 _ = async S.getAnswer(f, &data);
1159 try expect(data == 1234);
1160}
1161
1162test "@TypeOf an async function call of generic fn with error union type" {
1163 if (true) return error.SkipZigTest; // TODO
1164 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1165
1166 const S = struct {
1167 fn func(comptime x: anytype) anyerror!i32 {
1168 const T = @TypeOf(async func(x));
1169 comptime assert(T == @typeInfo(@TypeOf(@frame())).pointer.child);
1170 return undefined;
1171 }
1172 };
1173 _ = async S.func(i32);
1174}
1175
1176test "using @TypeOf on a generic function call" {
1177 if (true) return error.SkipZigTest; // TODO
1178 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1179
1180 const S = struct {
1181 var global_frame: anyframe = undefined;
1182 var global_ok = false;
1183
1184 var buf: [100]u8 align(16) = undefined;
1185
1186 fn amain(x: anytype) void {
1187 if (x == 0) {
1188 global_ok = true;
1189 return;
1190 }
1191 suspend {
1192 global_frame = @frame();
1193 }
1194 const F = @TypeOf(async amain(x - 1));
1195 const frame = @as(*F, @ptrFromInt(@intFromPtr(&buf)));
1196 return await @asyncCall(frame, {}, amain, .{x - 1});
1197 }
1198 };
1199 _ = async S.amain(@as(u32, 1));
1200 resume S.global_frame;
1201 try expect(S.global_ok);
1202}
1203
1204test "recursive call of await @asyncCall with struct return type" {
1205 if (true) return error.SkipZigTest; // TODO
1206 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1207
1208 const S = struct {
1209 var global_frame: anyframe = undefined;
1210 var global_ok = false;
1211
1212 var buf: [100]u8 align(16) = undefined;
1213
1214 fn amain(x: anytype) Foo {
1215 if (x == 0) {
1216 global_ok = true;
1217 return Foo{ .x = 1, .y = 2, .z = 3 };
1218 }
1219 suspend {
1220 global_frame = @frame();
1221 }
1222 const F = @TypeOf(async amain(x - 1));
1223 const frame = @as(*F, @ptrFromInt(@intFromPtr(&buf)));
1224 return await @asyncCall(frame, {}, amain, .{x - 1});
1225 }
1226
1227 const Foo = struct {
1228 x: u64,
1229 y: u64,
1230 z: u64,
1231 };
1232 };
1233 var res: S.Foo = undefined;
1234 var frame: @TypeOf(async S.amain(@as(u32, 1))) = undefined;
1235 _ = @asyncCall(&frame, &res, S.amain, .{@as(u32, 1)});
1236 resume S.global_frame;
1237 try expect(S.global_ok);
1238 try expect(res.x == 1);
1239 try expect(res.y == 2);
1240 try expect(res.z == 3);
1241}
1242
1243test "nosuspend function call" {
1244 if (true) return error.SkipZigTest; // TODO
1245 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1246
1247 const S = struct {
1248 fn doTheTest() !void {
1249 const result = nosuspend add(50, 100);
1250 try expect(result == 150);
1251 }
1252 fn add(a: i32, b: i32) i32 {
1253 if (a > 100) {
1254 suspend {}
1255 }
1256 return a + b;
1257 }
1258 };
1259 try S.doTheTest();
1260}
1261
1262test "await used in expression and awaiting fn with no suspend but async calling convention" {
1263 if (true) return error.SkipZigTest; // TODO
1264 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1265
1266 const S = struct {
1267 fn atest() void {
1268 var f1 = async add(1, 2);
1269 var f2 = async add(3, 4);
1270
1271 const sum = (await f1) + (await f2);
1272 expect(sum == 10) catch @panic("test failure");
1273 }
1274 fn add(a: i32, b: i32) callconv(.@"async") i32 {
1275 return a + b;
1276 }
1277 };
1278 _ = async S.atest();
1279}
1280
1281test "await used in expression after a fn call" {
1282 if (true) return error.SkipZigTest; // TODO
1283 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1284
1285 const S = struct {
1286 fn atest() void {
1287 var f1 = async add(3, 4);
1288 var sum: i32 = 0;
1289 sum = foo() + await f1;
1290 expect(sum == 8) catch @panic("test failure");
1291 }
1292 fn add(a: i32, b: i32) callconv(.@"async") i32 {
1293 return a + b;
1294 }
1295 fn foo() i32 {
1296 return 1;
1297 }
1298 };
1299 _ = async S.atest();
1300}
1301
1302test "async fn call used in expression after a fn call" {
1303 if (true) return error.SkipZigTest; // TODO
1304 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1305
1306 const S = struct {
1307 fn atest() void {
1308 var sum: i32 = 0;
1309 sum = foo() + add(3, 4);
1310 expect(sum == 8) catch @panic("test failure");
1311 }
1312 fn add(a: i32, b: i32) callconv(.@"async") i32 {
1313 return a + b;
1314 }
1315 fn foo() i32 {
1316 return 1;
1317 }
1318 };
1319 _ = async S.atest();
1320}
1321
1322test "suspend in for loop" {
1323 if (true) return error.SkipZigTest; // TODO
1324 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1325
1326 const S = struct {
1327 var global_frame: ?anyframe = null;
1328
1329 fn doTheTest() void {
1330 _ = async atest();
1331 while (global_frame) |f| resume f;
1332 }
1333
1334 fn atest() void {
1335 expect(func(&[_]u8{ 1, 2, 3 }) == 6) catch @panic("test failure");
1336 }
1337 fn func(stuff: []const u8) u32 {
1338 global_frame = @frame();
1339 var sum: u32 = 0;
1340 for (stuff) |x| {
1341 suspend {}
1342 sum += x;
1343 }
1344 global_frame = null;
1345 return sum;
1346 }
1347 };
1348 S.doTheTest();
1349}
1350
1351test "suspend in while loop" {
1352 if (true) return error.SkipZigTest; // TODO
1353 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1354
1355 const S = struct {
1356 var global_frame: ?anyframe = null;
1357
1358 fn doTheTest() void {
1359 _ = async atest();
1360 while (global_frame) |f| resume f;
1361 }
1362
1363 fn atest() void {
1364 expect(optional(6) == 6) catch @panic("test failure");
1365 expect(errunion(6) == 6) catch @panic("test failure");
1366 }
1367 fn optional(stuff: ?u32) u32 {
1368 global_frame = @frame();
1369 defer global_frame = null;
1370 while (stuff) |val| {
1371 suspend {}
1372 return val;
1373 }
1374 return 0;
1375 }
1376 fn errunion(stuff: anyerror!u32) u32 {
1377 global_frame = @frame();
1378 defer global_frame = null;
1379 while (stuff) |val| {
1380 suspend {}
1381 return val;
1382 } else |err| {
1383 err catch {};
1384 return 0;
1385 }
1386 }
1387 };
1388 S.doTheTest();
1389}
1390
1391test "correctly spill when returning the error union result of another async fn" {
1392 if (true) return error.SkipZigTest; // TODO
1393 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1394
1395 const S = struct {
1396 var global_frame: anyframe = undefined;
1397
1398 fn doTheTest() !void {
1399 expect((atest() catch unreachable) == 1234) catch @panic("test failure");
1400 }
1401
1402 fn atest() !i32 {
1403 return fallible1();
1404 }
1405
1406 fn fallible1() anyerror!i32 {
1407 suspend {
1408 global_frame = @frame();
1409 }
1410 return 1234;
1411 }
1412 };
1413 _ = async S.doTheTest();
1414 resume S.global_frame;
1415}
1416
1417test "spill target expr in a for loop" {
1418 if (true) return error.SkipZigTest; // TODO
1419 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1420
1421 const S = struct {
1422 var global_frame: anyframe = undefined;
1423
1424 fn doTheTest() !void {
1425 var foo = Foo{
1426 .slice = &[_]i32{ 1, 2 },
1427 };
1428 expect(atest(&foo) == 3) catch @panic("test failure");
1429 }
1430
1431 const Foo = struct {
1432 slice: []const i32,
1433 };
1434
1435 fn atest(foo: *Foo) i32 {
1436 var sum: i32 = 0;
1437 for (foo.slice) |x| {
1438 suspend {
1439 global_frame = @frame();
1440 }
1441 sum += x;
1442 }
1443 return sum;
1444 }
1445 };
1446 _ = async S.doTheTest();
1447 resume S.global_frame;
1448 resume S.global_frame;
1449}
1450
1451test "spill target expr in a for loop, with a var decl in the loop body" {
1452 if (true) return error.SkipZigTest; // TODO
1453 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1454
1455 const S = struct {
1456 var global_frame: anyframe = undefined;
1457
1458 fn doTheTest() !void {
1459 var foo = Foo{
1460 .slice = &[_]i32{ 1, 2 },
1461 };
1462 expect(atest(&foo) == 3) catch @panic("test failure");
1463 }
1464
1465 const Foo = struct {
1466 slice: []const i32,
1467 };
1468
1469 fn atest(foo: *Foo) i32 {
1470 var sum: i32 = 0;
1471 for (foo.slice) |x| {
1472 // Previously this var decl would prevent spills. This test makes sure
1473 // the for loop spills still happen even though there is a VarDecl in scope
1474 // before the suspend.
1475 var anything = true;
1476 _ = &anything;
1477 suspend {
1478 global_frame = @frame();
1479 }
1480 sum += x;
1481 }
1482 return sum;
1483 }
1484 };
1485 _ = async S.doTheTest();
1486 resume S.global_frame;
1487 resume S.global_frame;
1488}
1489
1490test "async call with @call" {
1491 if (true) return error.SkipZigTest; // TODO
1492 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1493
1494 const S = struct {
1495 var global_frame: anyframe = undefined;
1496 fn doTheTest() void {
1497 _ = @call(.{ .modifier = .async_kw }, atest, .{});
1498 resume global_frame;
1499 }
1500 fn atest() void {
1501 var frame = @call(.{ .modifier = .async_kw }, afoo, .{});
1502 const res = await frame;
1503 expect(res == 42) catch @panic("test failure");
1504 }
1505 fn afoo() i32 {
1506 suspend {
1507 global_frame = @frame();
1508 }
1509 return 42;
1510 }
1511 };
1512 S.doTheTest();
1513}
1514
1515test "async function passed 0-bit arg after non-0-bit arg" {
1516 if (true) return error.SkipZigTest; // TODO
1517 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1518
1519 const S = struct {
1520 var global_frame: anyframe = undefined;
1521 var global_int: i32 = 0;
1522
1523 fn foo() void {
1524 bar(1, .{}) catch unreachable;
1525 }
1526
1527 fn bar(x: i32, args: anytype) anyerror!void {
1528 _ = args;
1529 global_frame = @frame();
1530 suspend {}
1531 global_int = x;
1532 }
1533 };
1534 _ = async S.foo();
1535 resume S.global_frame;
1536 try expect(S.global_int == 1);
1537}
1538
1539test "async function passed align(16) arg after align(8) arg" {
1540 if (true) return error.SkipZigTest; // TODO
1541 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1542
1543 const S = struct {
1544 var global_frame: anyframe = undefined;
1545 var global_int: u128 = 0;
1546
1547 fn foo() void {
1548 var a: u128 = 99;
1549 _ = &a;
1550 bar(10, .{a}) catch unreachable;
1551 }
1552
1553 fn bar(x: u64, args: anytype) anyerror!void {
1554 try expect(x == 10);
1555 global_frame = @frame();
1556 suspend {}
1557 global_int = args[0];
1558 }
1559 };
1560 _ = async S.foo();
1561 resume S.global_frame;
1562 try expect(S.global_int == 99);
1563}
1564
1565test "async function call resolves target fn frame, comptime func" {
1566 if (true) return error.SkipZigTest; // TODO
1567 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1568
1569 const S = struct {
1570 var global_frame: anyframe = undefined;
1571 var global_int: i32 = 9;
1572
1573 fn foo() anyerror!void {
1574 const stack_size = 1000;
1575 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1576 return await @asyncCall(&stack_frame, {}, bar, .{});
1577 }
1578
1579 fn bar() anyerror!void {
1580 global_frame = @frame();
1581 suspend {}
1582 global_int += 1;
1583 }
1584 };
1585 _ = async S.foo();
1586 resume S.global_frame;
1587 try expect(S.global_int == 10);
1588}
1589
1590test "async function call resolves target fn frame, runtime func" {
1591 if (true) return error.SkipZigTest; // TODO
1592 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1593
1594 const S = struct {
1595 var global_frame: anyframe = undefined;
1596 var global_int: i32 = 9;
1597
1598 fn foo() anyerror!void {
1599 const stack_size = 1000;
1600 var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined;
1601 var func: fn () callconv(.@"async") anyerror!void = bar;
1602 _ = &func;
1603 return await @asyncCall(&stack_frame, {}, func, .{});
1604 }
1605
1606 fn bar() anyerror!void {
1607 global_frame = @frame();
1608 suspend {}
1609 global_int += 1;
1610 }
1611 };
1612 _ = async S.foo();
1613 resume S.global_frame;
1614 try expect(S.global_int == 10);
1615}
1616
1617test "properly spill optional payload capture value" {
1618 if (true) return error.SkipZigTest; // TODO
1619 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1620
1621 const S = struct {
1622 var global_frame: anyframe = undefined;
1623 var global_int: usize = 2;
1624
1625 fn foo() void {
1626 var opt: ?usize = 1234;
1627 _ = &opt;
1628 if (opt) |x| {
1629 bar();
1630 global_int += x;
1631 }
1632 }
1633
1634 fn bar() void {
1635 global_frame = @frame();
1636 suspend {}
1637 global_int += 1;
1638 }
1639 };
1640 _ = async S.foo();
1641 resume S.global_frame;
1642 try expect(S.global_int == 1237);
1643}
1644
1645test "handle defer interfering with return value spill" {
1646 if (true) return error.SkipZigTest; // TODO
1647 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1648
1649 const S = struct {
1650 var global_frame1: anyframe = undefined;
1651 var global_frame2: anyframe = undefined;
1652 var finished = false;
1653 var baz_happened = false;
1654
1655 fn doTheTest() !void {
1656 _ = async testFoo();
1657 resume global_frame1;
1658 resume global_frame2;
1659 try expect(baz_happened);
1660 try expect(finished);
1661 }
1662
1663 fn testFoo() void {
1664 expectError(error.Bad, foo()) catch @panic("test failure");
1665 finished = true;
1666 }
1667
1668 fn foo() anyerror!void {
1669 defer baz();
1670 return bar() catch |err| return err;
1671 }
1672
1673 fn bar() anyerror!void {
1674 global_frame1 = @frame();
1675 suspend {}
1676 return error.Bad;
1677 }
1678
1679 fn baz() void {
1680 global_frame2 = @frame();
1681 suspend {}
1682 baz_happened = true;
1683 }
1684 };
1685 try S.doTheTest();
1686}
1687
1688test "take address of temporary async frame" {
1689 if (true) return error.SkipZigTest; // TODO
1690 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1691
1692 const S = struct {
1693 var global_frame: anyframe = undefined;
1694 var finished = false;
1695
1696 fn doTheTest() !void {
1697 _ = async asyncDoTheTest();
1698 resume global_frame;
1699 try expect(finished);
1700 }
1701
1702 fn asyncDoTheTest() void {
1703 expect(finishIt(&async foo(10)) == 1245) catch @panic("test failure");
1704 finished = true;
1705 }
1706
1707 fn foo(arg: i32) i32 {
1708 global_frame = @frame();
1709 suspend {}
1710 return arg + 1234;
1711 }
1712
1713 fn finishIt(frame: anyframe->i32) i32 {
1714 return (await frame) + 1;
1715 }
1716 };
1717 try S.doTheTest();
1718}
1719
1720test "nosuspend await" {
1721 if (true) return error.SkipZigTest; // TODO
1722 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1723
1724 const S = struct {
1725 var finished = false;
1726
1727 fn doTheTest() !void {
1728 var frame = async foo(false);
1729 try expect(nosuspend await frame == 42);
1730 finished = true;
1731 }
1732
1733 fn foo(want_suspend: bool) i32 {
1734 if (want_suspend) {
1735 suspend {}
1736 }
1737 return 42;
1738 }
1739 };
1740 try S.doTheTest();
1741 try expect(S.finished);
1742}
1743
1744test "nosuspend on function calls" {
1745 if (true) return error.SkipZigTest; // TODO
1746 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1747
1748 const S0 = struct {
1749 b: i32 = 42,
1750 };
1751 const S1 = struct {
1752 fn c() S0 {
1753 return S0{};
1754 }
1755 fn d() !S0 {
1756 return S0{};
1757 }
1758 };
1759 try expectEqual(@as(i32, 42), nosuspend S1.c().b);
1760 try expectEqual(@as(i32, 42), (try nosuspend S1.d()).b);
1761}
1762
1763test "nosuspend on async function calls" {
1764 if (true) return error.SkipZigTest; // TODO
1765 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1766
1767 const S0 = struct {
1768 b: i32 = 42,
1769 };
1770 const S1 = struct {
1771 fn c() S0 {
1772 return S0{};
1773 }
1774 fn d() !S0 {
1775 return S0{};
1776 }
1777 };
1778 var frame_c = nosuspend async S1.c();
1779 try expectEqual(@as(i32, 42), (await frame_c).b);
1780 var frame_d = nosuspend async S1.d();
1781 try expectEqual(@as(i32, 42), (try await frame_d).b);
1782}
1783
1784// test "resume nosuspend async function calls" {
1785// if (true) return error.SkipZigTest; // if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1786// const S0 = struct {
1787// b: i32 = 42,
1788// };
1789// const S1 = struct {
1790// fn c() S0 {
1791// suspend {}
1792// return S0{};
1793// }
1794// fn d() !S0 {
1795// suspend {}
1796// return S0{};
1797// }
1798// };
1799// var frame_c = nosuspend async S1.c();
1800// resume frame_c;
1801// try expectEqual(@as(i32, 42), (await frame_c).b);
1802// var frame_d = nosuspend async S1.d();
1803// resume frame_d;
1804// try expectEqual(@as(i32, 42), (try await frame_d).b);
1805// }
1806
1807test "nosuspend resume async function calls" {
1808 if (true) return error.SkipZigTest; // TODO
1809 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1810
1811 const S0 = struct {
1812 b: i32 = 42,
1813 };
1814 const S1 = struct {
1815 fn c() S0 {
1816 suspend {}
1817 return S0{};
1818 }
1819 fn d() !S0 {
1820 suspend {}
1821 return S0{};
1822 }
1823 };
1824 var frame_c = async S1.c();
1825 nosuspend resume frame_c;
1826 try expectEqual(@as(i32, 42), (await frame_c).b);
1827 var frame_d = async S1.d();
1828 nosuspend resume frame_d;
1829 try expectEqual(@as(i32, 42), (try await frame_d).b);
1830}
1831
1832test "avoid forcing frame alignment resolution implicit cast to *anyopaque" {
1833 if (true) return error.SkipZigTest; // TODO
1834 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1835
1836 const S = struct {
1837 var x: ?*anyopaque = null;
1838
1839 fn foo() bool {
1840 suspend {
1841 x = @frame();
1842 }
1843 return true;
1844 }
1845 };
1846 var frame = async S.foo();
1847 resume @as(anyframe->bool, @ptrCast(@alignCast(S.x)));
1848 try expect(nosuspend await frame);
1849}
1850
1851test "@asyncCall with pass-by-value arguments" {
1852 if (true) return error.SkipZigTest; // TODO
1853 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1854
1855 const F0: u64 = 0xbeefbeefbeefbeef;
1856 const F1: u64 = 0xf00df00df00df00d;
1857 const F2: u64 = 0xcafecafecafecafe;
1858
1859 const S = struct {
1860 pub const ST = struct { f0: usize, f1: usize };
1861 pub const AT = [5]u8;
1862
1863 pub fn f(_fill0: u64, s: ST, _fill1: u64, a: AT, _fill2: u64) callconv(.@"async") void {
1864 _ = s;
1865 _ = a;
1866 // Check that the array and struct arguments passed by value don't
1867 // end up overflowing the adjacent fields in the frame structure.
1868 expectEqual(F0, _fill0) catch @panic("test failure");
1869 expectEqual(F1, _fill1) catch @panic("test failure");
1870 expectEqual(F2, _fill2) catch @panic("test failure");
1871 }
1872 };
1873
1874 var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined;
1875 // The function pointer must not be comptime-known.
1876 var t = S.f;
1877 _ = &t;
1878 var frame_ptr = @asyncCall(&buffer, {}, t, .{
1879 F0,
1880 .{ .f0 = 1, .f1 = 2 },
1881 F1,
1882 [_]u8{ 1, 2, 3, 4, 5 },
1883 F2,
1884 });
1885 _ = &frame_ptr;
1886}
1887
1888test "@asyncCall with arguments having non-standard alignment" {
1889 if (true) return error.SkipZigTest; // TODO
1890 if (builtin.os.tag == .wasi) return error.SkipZigTest; // TODO
1891
1892 const F0: u64 = 0xbeefbeef;
1893 const F1: u64 = 0xf00df00df00df00d;
1894
1895 const S = struct {
1896 pub fn f(_fill0: u32, s: struct { x: u64 align(16) }, _fill1: u64) callconv(.@"async") void {
1897 _ = s;
1898 // The compiler inserts extra alignment for s, check that the
1899 // generated code picks the right slot for fill1.
1900 expectEqual(F0, _fill0) catch @panic("test failure");
1901 expectEqual(F1, _fill1) catch @panic("test failure");
1902 }
1903 };
1904
1905 var buffer: [1024]u8 align(@alignOf(@Frame(S.f))) = undefined;
1906 // The function pointer must not be comptime-known.
1907 var t = S.f;
1908 _ = &t;
1909 var frame_ptr = @asyncCall(&buffer, {}, t, .{ F0, undefined, F1 });
1910 _ = &frame_ptr;
1911}
test/behavior/await_struct.zig deleted-47
......@@ -1,47 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: anyframe = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 if (true) return error.SkipZigTest; // TODO
14
15 await_seq('a');
16 var p = async await_amain();
17 _ = &p;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 try expect(await_final_result.x == 1234);
22 try expect(std.mem.eql(u8, &await_points, "abcdefghi"));
23}
24fn await_amain() callconv(.@"async") void {
25 await_seq('b');
26 var p = async await_another();
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31fn await_another() callconv(.@"async") Foo {
32 await_seq('c');
33 suspend {
34 await_seq('d');
35 await_a_promise = @frame();
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = [_]u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/behavior/call.zig+3-3
......@@ -37,7 +37,7 @@ test "basic invocations" {
3737 comptime {
3838 // comptime calls with supported modifiers
3939 try expect(@call(.auto, foo, .{2}) == 1234);
40 try expect(@call(.no_async, foo, .{3}) == 1234);
40 try expect(@call(.no_suspend, foo, .{3}) == 1234);
4141 try expect(@call(.always_tail, foo, .{4}) == 1234);
4242 try expect(@call(.always_inline, foo, .{5}) == 1234);
4343 }
......@@ -45,7 +45,7 @@ test "basic invocations" {
4545 const result = @call(.compile_time, foo, .{6}) == 1234;
4646 comptime assert(result);
4747 // runtime calls of comptime-known function
48 try expect(@call(.no_async, foo, .{7}) == 1234);
48 try expect(@call(.no_suspend, foo, .{7}) == 1234);
4949 try expect(@call(.never_tail, foo, .{8}) == 1234);
5050 try expect(@call(.never_inline, foo, .{9}) == 1234);
5151 // CBE does not support attributes on runtime functions
......@@ -53,7 +53,7 @@ test "basic invocations" {
5353 // runtime calls of non comptime-known function
5454 var alias_foo = &foo;
5555 _ = &alias_foo;
56 try expect(@call(.no_async, alias_foo, .{10}) == 1234);
56 try expect(@call(.no_suspend, alias_foo, .{10}) == 1234);
5757 try expect(@call(.never_tail, alias_foo, .{11}) == 1234);
5858 try expect(@call(.never_inline, alias_foo, .{12}) == 1234);
5959 }
test/cases/compile_errors/async/async_function_depends_on_its_own_frame.zig deleted-13
......@@ -1,13 +0,0 @@
1export fn entry() void {
2 _ = async amain();
3}
4fn amain() callconv(.@"async") void {
5 var x: [@sizeOf(@Frame(amain))]u8 = undefined;
6 _ = &x;
7}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:4:1: error: cannot resolve '@Frame(amain)': function not fully analyzed yet
test/cases/compile_errors/async/async_function_indirectly_depends_on_its_own_frame.zig deleted-17
......@@ -1,17 +0,0 @@
1export fn entry() void {
2 _ = async amain();
3}
4fn amain() callconv(.@"async") void {
5 other();
6}
7fn other() void {
8 var x: [@sizeOf(@Frame(amain))]u8 = undefined;
9 _ = &x;
10}
11
12// error
13// backend=stage1
14// target=native
15//
16// tmp.zig:4:1: error: unable to determine async function frame of 'amain'
17// tmp.zig:5:10: note: analysis of function 'other' depends on the frame
test/cases/compile_errors/async/const_frame_cast_to_anyframe.zig deleted-19
......@@ -1,19 +0,0 @@
1export fn a() void {
2 const f = async func();
3 resume f;
4}
5export fn b() void {
6 const f = async func();
7 var x: anyframe = &f;
8 _ = &x;
9}
10fn func() void {
11 suspend {}
12}
13
14// error
15// backend=stage1
16// target=native
17//
18// tmp.zig:3:12: error: expected type 'anyframe', found '*const @Frame(func)'
19// tmp.zig:7:24: error: expected type 'anyframe', found '*const @Frame(func)'
test/cases/compile_errors/async/function_with_ccc_indirectly_calling_async_function.zig deleted-18
......@@ -1,18 +0,0 @@
1export fn entry() void {
2 foo();
3}
4fn foo() void {
5 bar();
6}
7fn bar() void {
8 suspend {}
9}
10
11// error
12// backend=stage1
13// target=native
14//
15// tmp.zig:1:1: error: function with calling convention 'C' cannot be async
16// tmp.zig:2:8: note: async function call here
17// tmp.zig:5:8: note: async function call here
18// tmp.zig:8:5: note: suspends here
test/cases/compile_errors/async/indirect_recursion_of_async_functions_detected.zig deleted-36
......@@ -1,36 +0,0 @@
1var frame: ?anyframe = null;
2
3export fn a() void {
4 _ = async rangeSum(10);
5 while (frame) |f| resume f;
6}
7
8fn rangeSum(x: i32) i32 {
9 suspend {
10 frame = @frame();
11 }
12 frame = null;
13
14 if (x == 0) return 0;
15 const child = rangeSumIndirect(x - 1);
16 return child + 1;
17}
18
19fn rangeSumIndirect(x: i32) i32 {
20 suspend {
21 frame = @frame();
22 }
23 frame = null;
24
25 if (x == 0) return 0;
26 const child = rangeSum(x - 1);
27 return child + 1;
28}
29
30// error
31// backend=stage1
32// target=native
33//
34// tmp.zig:8:1: error: '@Frame(rangeSum)' depends on itself
35// tmp.zig:15:35: note: when analyzing type '@Frame(rangeSum)' here
36// tmp.zig:28:25: note: when analyzing type '@Frame(rangeSumIndirect)' here
test/cases/compile_errors/async/invalid_suspend_in_exported_function.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var frame = async func();
3 var result = await frame;
4 _ = &result;
5}
6fn func() void {
7 suspend {}
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:1:1: error: function with calling convention 'C' cannot be async
15// tmp.zig:3:18: note: await here is a suspend point
test/cases/compile_errors/async/returning_error_from_void_async_function.zig deleted-12
......@@ -1,12 +0,0 @@
1export fn entry() void {
2 _ = async amain();
3}
4fn amain() callconv(.@"async") void {
5 return error.ShouldBeCompileError;
6}
7
8// error
9// backend=stage1
10// target=native
11//
12// tmp.zig:5:17: error: expected type 'void', found 'error{ShouldBeCompileError}'
test/cases/compile_errors/async/runtime-known_async_function_called.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 _ = async amain();
3}
4fn amain() void {
5 var ptr = afunc;
6 _ = ptr();
7 _ = &ptr;
8}
9fn afunc() callconv(.@"async") void {}
10
11// error
12// backend=stage1
13// target=native
14//
15// tmp.zig:6:12: error: function is not comptime-known; @asyncCall required
test/cases/compile_errors/async/runtime-known_function_called_with_async_keyword.zig deleted-13
......@@ -1,13 +0,0 @@
1export fn entry() void {
2 var ptr = afunc;
3 _ = async ptr();
4 _ = &ptr;
5}
6
7fn afunc() callconv(.@"async") void {}
8
9// error
10// backend=stage1
11// target=native
12//
13// tmp.zig:3:15: error: function is not comptime-known; @asyncCall required
test/cases/compile_errors/async/wrong_frame_type_used_for_async_call.zig deleted-16
......@@ -1,16 +0,0 @@
1export fn entry() void {
2 var frame: @Frame(foo) = undefined;
3 frame = async bar();
4}
5fn foo() void {
6 suspend {}
7}
8fn bar() void {
9 suspend {}
10}
11
12// error
13// backend=stage1
14// target=native
15//
16// tmp.zig:3:13: error: expected type '*@Frame(bar)', found '*@Frame(foo)'
test/cases/compile_errors/async/wrong_type_for_result_ptr_to_asyncCall.zig deleted-16
......@@ -1,16 +0,0 @@
1export fn entry() void {
2 _ = async amain();
3}
4fn amain() i32 {
5 var frame: @Frame(foo) = undefined;
6 return await @asyncCall(&frame, false, foo, .{});
7}
8fn foo() i32 {
9 return 1234;
10}
11
12// error
13// backend=stage1
14// target=native
15//
16// tmp.zig:6:37: error: expected type '*i32', found 'bool'
test/cases/compile_errors/combination_of_nosuspend_and_async.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 nosuspend {
3 const bar = async foo();
4 suspend {}
5 resume bar;
6 }
7}
8fn foo() void {}
9
10// error
11// backend=stage2
12// target=native
13//
14// :4:9: error: suspend inside nosuspend block
15// :2:5: note: nosuspend block here
test/cases/compile_errors/suspend_inside_suspend_block.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 _ = async foo();
3}
4fn foo() void {
5 suspend {
6 suspend {}
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :6:9: error: cannot suspend inside suspend block
15// :5:5: note: other suspend block here
test/cases/safety/@asyncCall with too small a frame.zig deleted-26
......@@ -1,26 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
5 _ = message;
6 _ = stack_trace;
7 std.process.exit(0);
8}
9pub fn main() !void {
10 if (builtin.zig_backend == .stage1 and builtin.os.tag == .wasi) {
11 // TODO file a bug for this failure
12 std.process.exit(0); // skip the test
13 }
14 var bytes: [1]u8 align(16) = undefined;
15 var ptr = other;
16 _ = &ptr;
17 var frame = @asyncCall(&bytes, {}, ptr, .{});
18 _ = &frame;
19 return error.TestFailed;
20}
21fn other() callconv(.@"async") void {
22 suspend {}
23}
24// run
25// backend=stage1
26// target=native
test/cases/safety/awaiting twice.zig deleted-29
......@@ -1,29 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = message;
5 _ = stack_trace;
6 std.process.exit(0);
7}
8var frame: anyframe = undefined;
9
10pub fn main() !void {
11 _ = async amain();
12 resume frame;
13 return error.TestFailed;
14}
15
16fn amain() void {
17 var f = async func();
18 await f;
19 await f;
20}
21
22fn func() void {
23 suspend {
24 frame = @frame();
25 }
26}
27// run
28// backend=stage1
29// target=native
test/cases/safety/error return trace across suspend points.zig deleted-38
......@@ -1,38 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = message;
5 _ = stack_trace;
6 std.process.exit(0);
7}
8
9var failing_frame: @Frame(failing) = undefined;
10
11pub fn main() !void {
12 const p = nonFailing();
13 resume p;
14 const p2 = async printTrace(p);
15 _ = p2;
16 return error.TestFailed;
17}
18
19fn nonFailing() anyframe->anyerror!void {
20 failing_frame = async failing();
21 return &failing_frame;
22}
23
24fn failing() anyerror!void {
25 suspend {}
26 return second();
27}
28
29fn second() callconv(.@"async") anyerror!void {
30 return error.Fail;
31}
32
33fn printTrace(p: anyframe->anyerror!void) void {
34 (await p) catch unreachable;
35}
36// run
37// backend=stage1
38// target=native
test/cases/safety/invalid resume of async function.zig deleted-19
......@@ -1,19 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = message;
5 _ = stack_trace;
6 std.process.exit(0);
7}
8pub fn main() !void {
9 var p = async suspendOnce();
10 resume p; //ok
11 resume p; //bad
12 return error.TestFailed;
13}
14fn suspendOnce() void {
15 suspend {}
16}
17// run
18// backend=stage1
19// target=native
test/cases/safety/resuming a function which is awaiting a call.zig deleted-21
......@@ -1,21 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = message;
5 _ = stack_trace;
6 std.process.exit(0);
7}
8pub fn main() !void {
9 var frame = async first();
10 resume frame;
11 return error.TestFailed;
12}
13fn first() void {
14 other();
15}
16fn other() void {
17 suspend {}
18}
19// run
20// backend=stage1
21// target=native
test/cases/safety/resuming a function which is awaiting a frame.zig deleted-22
......@@ -1,22 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = message;
5 _ = stack_trace;
6 std.process.exit(0);
7}
8pub fn main() !void {
9 var frame = async first();
10 resume frame;
11 return error.TestFailed;
12}
13fn first() void {
14 var frame = async other();
15 await frame;
16}
17fn other() void {
18 suspend {}
19}
20// run
21// backend=stage1
22// target=native
test/cases/safety/resuming a non-suspended function which has been suspended and resumed.zig deleted-32
......@@ -1,32 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = message;
5 _ = stack_trace;
6 std.process.exit(0);
7}
8fn foo() void {
9 suspend {
10 global_frame = @frame();
11 }
12 var f = async bar(@frame());
13 _ = &f;
14 std.process.exit(1);
15}
16
17fn bar(frame: anyframe) void {
18 suspend {
19 resume frame;
20 }
21 std.process.exit(1);
22}
23
24var global_frame: anyframe = undefined;
25pub fn main() !void {
26 _ = async foo();
27 resume global_frame;
28 std.process.exit(1);
29}
30// run
31// backend=stage1
32// target=native
test/cases/safety/resuming a non-suspended function which never been suspended.zig deleted-27
......@@ -1,27 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = message;
5 _ = stack_trace;
6 std.process.exit(0);
7}
8fn foo() void {
9 var f = async bar(@frame());
10 _ = &f;
11 std.process.exit(1);
12}
13
14fn bar(frame: anyframe) void {
15 suspend {
16 resume frame;
17 }
18 std.process.exit(1);
19}
20
21pub fn main() !void {
22 _ = async foo();
23 return error.TestFailed;
24}
25// run
26// backend=stage1
27// target=native
tools/docgen.zig-2
......@@ -710,8 +710,6 @@ fn tokenizeAndPrintRaw(
710710 .keyword_align,
711711 .keyword_and,
712712 .keyword_asm,
713 .keyword_async,
714 .keyword_await,
715713 .keyword_break,
716714 .keyword_catch,
717715 .keyword_comptime,
tools/doctest.zig-2
......@@ -653,8 +653,6 @@ fn tokenizeAndPrint(arena: Allocator, out: anytype, raw_src: []const u8) !void {
653653 .keyword_align,
654654 .keyword_and,
655655 .keyword_asm,
656 .keyword_async,
657 .keyword_await,
658656 .keyword_break,
659657 .keyword_catch,
660658 .keyword_comptime,
tools/lldb_pretty_printers.py-2
......@@ -50,8 +50,6 @@ zig_keywords = {
5050 'anyframe',
5151 'anytype',
5252 'asm',
53 'async',
54 'await',
5553 'break',
5654 'callconv',
5755 'catch',