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 {...@@ -4279,16 +4279,9 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
4279 {#header_close#}4279 {#header_close#}
42804280
4281 {#header_open|Async Functions#}4281 {#header_open|Async Functions#}
4282 <p>Async functions regressed with the release of 0.11.0. Their future in4282 <p>Async functions regressed with the release of 0.11.0. The current plan is to
4283 the Zig language is unclear due to multiple unsolved problems:</p>4283 reintroduce them as a lower level primitive that powers I/O implementations.</p>
4284 <ul>4284 <p>Tracking issue: <a href="https://github.com/ziglang/zig/issues/23446">Proposal: stackless coroutines as low-level primitives</a></p>
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>
4292 {#header_close#}4285 {#header_close#}
42934286
4294 {#header_open|Builtin Functions|2col#}4287 {#header_open|Builtin Functions|2col#}
...@@ -7372,29 +7365,6 @@ fn readU32Be() u32 {}...@@ -7372,29 +7365,6 @@ fn readU32Be() u32 {}
7372 </ul>7365 </ul>
7373 </td>7366 </td>
7374 </tr>7367 </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>
7398 <tr>7368 <tr>
7399 <th scope="row">7369 <th scope="row">
7400 <pre>{#syntax#}break{#endsyntax#}</pre>7370 <pre>{#syntax#}break{#endsyntax#}</pre>
...@@ -8006,8 +7976,7 @@ TypeExpr <- PrefixTypeOp* ErrorUnionExpr...@@ -8006,8 +7976,7 @@ TypeExpr <- PrefixTypeOp* ErrorUnionExpr
8006ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?7976ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
80077977
8008SuffixExpr7978SuffixExpr
8009 <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments7979 <- PrimaryTypeExpr (SuffixOp / FnCallArguments)*
8010 / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
80117980
8012PrimaryTypeExpr7981PrimaryTypeExpr
8013 <- BUILTINIDENTIFIER FnCallArguments7982 <- BUILTINIDENTIFIER FnCallArguments
...@@ -8183,7 +8152,6 @@ PrefixOp...@@ -8183,7 +8152,6 @@ PrefixOp
8183 / MINUSPERCENT8152 / MINUSPERCENT
8184 / AMPERSAND8153 / AMPERSAND
8185 / KEYWORD_try8154 / KEYWORD_try
8186 / KEYWORD_await
81878155
8188PrefixTypeOp8156PrefixTypeOp
8189 <- QUESTIONMARK8157 <- QUESTIONMARK
...@@ -8404,8 +8372,6 @@ KEYWORD_and <- 'and' end_of_word...@@ -8404,8 +8372,6 @@ KEYWORD_and <- 'and' end_of_word
8404KEYWORD_anyframe <- 'anyframe' end_of_word8372KEYWORD_anyframe <- 'anyframe' end_of_word
8405KEYWORD_anytype <- 'anytype' end_of_word8373KEYWORD_anytype <- 'anytype' end_of_word
8406KEYWORD_asm <- 'asm' end_of_word8374KEYWORD_asm <- 'asm' end_of_word
8407KEYWORD_async <- 'async' end_of_word
8408KEYWORD_await <- 'await' end_of_word
8409KEYWORD_break <- 'break' end_of_word8375KEYWORD_break <- 'break' end_of_word
8410KEYWORD_callconv <- 'callconv' end_of_word8376KEYWORD_callconv <- 'callconv' end_of_word
8411KEYWORD_catch <- 'catch' end_of_word8377KEYWORD_catch <- 'catch' end_of_word
...@@ -8448,8 +8414,8 @@ KEYWORD_volatile <- 'volatile' end_of_word...@@ -8448,8 +8414,8 @@ KEYWORD_volatile <- 'volatile' end_of_word
8448KEYWORD_while <- 'while' end_of_word8414KEYWORD_while <- 'while' end_of_word
84498415
8450keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and8416keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and
8451 / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async8417 / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm
8452 / KEYWORD_await / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch8418 / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch
8453 / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer8419 / KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer
8454 / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export8420 / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export
8455 / KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if8421 / 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 {...@@ -335,7 +335,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
335 .address_of,335 .address_of,
336 .@"try",336 .@"try",
337 .@"resume",337 .@"resume",
338 .@"await",
339 .deref,338 .deref,
340 => {339 => {
341 return walkExpression(w, ast.nodeData(node).node);340 return walkExpression(w, ast.nodeData(node).node);
...@@ -379,12 +378,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -379,12 +378,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
379378
380 .call_one,379 .call_one,
381 .call_one_comma,380 .call_one_comma,
382 .async_call_one,
383 .async_call_one_comma,
384 .call,381 .call,
385 .call_comma,382 .call_comma,
386 .async_call,
387 .async_call_comma,
388 => {383 => {
389 var buf: [1]Ast.Node.Index = undefined;384 var buf: [1]Ast.Node.Index = undefined;
390 return walkCall(w, ast.fullCall(&buf, node).?);385 return walkCall(w, ast.fullCall(&buf, node).?);
lib/docs/wasm/Walk.zig-9
...@@ -238,12 +238,8 @@ pub const File = struct {...@@ -238,12 +238,8 @@ pub const File = struct {
238238
239 .call_one,239 .call_one,
240 .call_one_comma,240 .call_one_comma,
241 .async_call_one,
242 .async_call_one_comma,
243 .call,241 .call,
244 .call_comma,242 .call_comma,
245 .async_call,
246 .async_call_comma,
247 => {243 => {
248 var buf: [1]Ast.Node.Index = undefined;244 var buf: [1]Ast.Node.Index = undefined;
249 return categorize_call(file_index, node, ast.fullCall(&buf, node).?);245 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)...@@ -743,7 +739,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
743 .@"comptime",739 .@"comptime",
744 .@"nosuspend",740 .@"nosuspend",
745 .@"suspend",741 .@"suspend",
746 .@"await",
747 .@"resume",742 .@"resume",
748 .@"try",743 .@"try",
749 => try expr(w, scope, parent_decl, ast.nodeData(node).node),744 => 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)...@@ -806,12 +801,8 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
806801
807 .call_one,802 .call_one,
808 .call_one_comma,803 .call_one_comma,
809 .async_call_one,
810 .async_call_one_comma,
811 .call,804 .call,
812 .call_comma,805 .call_comma,
813 .async_call,
814 .async_call_comma,
815 => {806 => {
816 var buf: [1]Ast.Node.Index = undefined;807 var buf: [1]Ast.Node.Index = undefined;
817 const full = ast.fullCall(&buf, node).?;808 const full = ast.fullCall(&buf, node).?;
lib/docs/wasm/html_render.zig-2
...@@ -101,8 +101,6 @@ pub fn fileSourceHtml(...@@ -101,8 +101,6 @@ pub fn fileSourceHtml(
101 .keyword_align,101 .keyword_align,
102 .keyword_and,102 .keyword_and,
103 .keyword_asm,103 .keyword_asm,
104 .keyword_async,
105 .keyword_await,
106 .keyword_break,104 .keyword_break,
107 .keyword_catch,105 .keyword_catch,
108 .keyword_comptime,106 .keyword_comptime,
lib/std/builtin.zig+1-12
...@@ -199,8 +199,6 @@ pub const CallingConvention = union(enum(u8)) {...@@ -199,8 +199,6 @@ pub const CallingConvention = union(enum(u8)) {
199 pub const C: CallingConvention = .c;199 pub const C: CallingConvention = .c;
200 /// Deprecated; use `.naked`.200 /// Deprecated; use `.naked`.
201 pub const Naked: CallingConvention = .naked;201 pub const Naked: CallingConvention = .naked;
202 /// Deprecated; use `.@"async"`.
203 pub const Async: CallingConvention = .@"async";
204 /// Deprecated; use `.@"inline"`.202 /// Deprecated; use `.@"inline"`.
205 pub const Inline: CallingConvention = .@"inline";203 pub const Inline: CallingConvention = .@"inline";
206 /// Deprecated; use `.x86_64_interrupt`, `.x86_interrupt`, or `.avr_interrupt`.204 /// Deprecated; use `.x86_64_interrupt`, `.x86_interrupt`, or `.avr_interrupt`.
...@@ -866,32 +864,23 @@ pub const WasiExecModel = enum {...@@ -866,32 +864,23 @@ pub const WasiExecModel = enum {
866pub const CallModifier = enum {864pub const CallModifier = enum {
867 /// Equivalent to function call syntax.865 /// Equivalent to function call syntax.
868 auto,866 auto,
869
870 /// Equivalent to async keyword used with function call syntax.
871 async_kw,
872
873 /// Prevents tail call optimization. This guarantees that the return867 /// Prevents tail call optimization. This guarantees that the return
874 /// address will point to the callsite, as opposed to the callsite's868 /// address will point to the callsite, as opposed to the callsite's
875 /// callsite. If the call is otherwise required to be tail-called869 /// callsite. If the call is otherwise required to be tail-called
876 /// or inlined, a compile error is emitted instead.870 /// or inlined, a compile error is emitted instead.
877 never_tail,871 never_tail,
878
879 /// Guarantees that the call will not be inlined. If the call is872 /// Guarantees that the call will not be inlined. If the call is
880 /// otherwise required to be inlined, a compile error is emitted instead.873 /// otherwise required to be inlined, a compile error is emitted instead.
881 never_inline,874 never_inline,
882
883 /// Asserts that the function call will not suspend. This allows a875 /// Asserts that the function call will not suspend. This allows a
884 /// non-async function to call an async function.876 /// non-async function to call an async function.
885 no_async,877 no_suspend,
886
887 /// Guarantees that the call will be generated with tail call optimization.878 /// Guarantees that the call will be generated with tail call optimization.
888 /// If this is not possible, a compile error is emitted instead.879 /// If this is not possible, a compile error is emitted instead.
889 always_tail,880 always_tail,
890
891 /// Guarantees that the call will be inlined at the callsite.881 /// Guarantees that the call will be inlined at the callsite.
892 /// If this is not possible, a compile error is emitted instead.882 /// If this is not possible, a compile error is emitted instead.
893 always_inline,883 always_inline,
894
895 /// Evaluates the call at compile-time. If the call cannot be completed at884 /// Evaluates the call at compile-time. If the call cannot be completed at
896 /// compile-time, a compile error is emitted instead.885 /// compile-time, a compile error is emitted instead.
897 compile_time,886 compile_time,
lib/std/zig/Ast.zig+7-64
...@@ -606,7 +606,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -606,7 +606,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
606 .negation_wrap,606 .negation_wrap,
607 .address_of,607 .address_of,
608 .@"try",608 .@"try",
609 .@"await",
610 .optional_type,609 .optional_type,
611 .@"switch",610 .@"switch",
612 .switch_comma,611 .switch_comma,
...@@ -763,20 +762,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -763,20 +762,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
763 return main_token - end_offset;762 return main_token - end_offset;
764 },763 },
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
780 .container_field_init,765 .container_field_init,
781 .container_field_align,766 .container_field_align,
782 .container_field,767 .container_field,
...@@ -903,7 +888,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -903,7 +888,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
903 .negation_wrap,888 .negation_wrap,
904 .address_of,889 .address_of,
905 .@"try",890 .@"try",
906 .@"await",
907 .optional_type,891 .optional_type,
908 .@"suspend",892 .@"suspend",
909 .@"resume",893 .@"resume",
...@@ -1022,7 +1006,7 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1022,7 +1006,7 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1022 };1006 };
1023 },1007 },
10241008
1025 .call, .async_call => {1009 .call => {
1026 _, const extra_index = tree.nodeData(n).node_and_extra;1010 _, const extra_index = tree.nodeData(n).node_and_extra;
1027 const params = tree.extraData(extra_index, Node.SubRange);1011 const params = tree.extraData(extra_index, Node.SubRange);
1028 assert(params.start != params.end);1012 assert(params.start != params.end);
...@@ -1041,7 +1025,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1041,7 +1025,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1041 }1025 }
1042 },1026 },
1043 .call_comma,1027 .call_comma,
1044 .async_call_comma,
1045 .tagged_union_enum_tag_trailing,1028 .tagged_union_enum_tag_trailing,
1046 => {1029 => {
1047 _, const extra_index = tree.nodeData(n).node_and_extra;1030 _, const extra_index = tree.nodeData(n).node_and_extra;
...@@ -1122,7 +1105,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1122,7 +1105,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1122 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member1105 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member
1123 },1106 },
1124 .call_one,1107 .call_one,
1125 .async_call_one,
1126 => {1108 => {
1127 _, const first_param = tree.nodeData(n).node_and_opt_node;1109 _, const first_param = tree.nodeData(n).node_and_opt_node;
1128 end_offset += 1; // for the rparen1110 end_offset += 1; // for the rparen
...@@ -1271,7 +1253,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1271,7 +1253,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1271 n = first_element;1253 n = first_element;
1272 },1254 },
1273 .call_one_comma,1255 .call_one_comma,
1274 .async_call_one_comma,
1275 .struct_init_one_comma,1256 .struct_init_one_comma,
1276 => {1257 => {
1277 _, const first_field = tree.nodeData(n).node_and_opt_node;1258 _, const first_field = tree.nodeData(n).node_and_opt_node;
...@@ -1988,21 +1969,21 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {...@@ -1988,21 +1969,21 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {
1988pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {1969pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {
1989 const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;1970 const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;
1990 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});1971 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
1991 return tree.fullCallComponents(.{1972 return .{ .ast = .{
1992 .lparen = tree.nodeMainToken(node),1973 .lparen = tree.nodeMainToken(node),
1993 .fn_expr = fn_expr,1974 .fn_expr = fn_expr,
1994 .params = params,1975 .params = params,
1995 });1976 } };
1996}1977}
19971978
1998pub fn callFull(tree: Ast, node: Node.Index) full.Call {1979pub fn callFull(tree: Ast, node: Node.Index) full.Call {
1999 const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;1980 const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;
2000 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);1981 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
2001 return tree.fullCallComponents(.{1982 return .{ .ast = .{
2002 .lparen = tree.nodeMainToken(node),1983 .lparen = tree.nodeMainToken(node),
2003 .fn_expr = fn_expr,1984 .fn_expr = fn_expr,
2004 .params = params,1985 .params = params,
2005 });1986 } };
2006}1987}
20071988
2008fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {1989fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {
...@@ -2336,18 +2317,6 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {...@@ -2336,18 +2317,6 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
2336 return result;2317 return result;
2337}2318}
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
2351pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {2320pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
2352 return switch (tree.nodeTag(node)) {2321 return switch (tree.nodeTag(node)) {
2353 .global_var_decl => tree.globalVarDecl(node),2322 .global_var_decl => tree.globalVarDecl(node),
...@@ -2488,8 +2457,8 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {...@@ -2488,8 +2457,8 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
24882457
2489pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {2458pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {
2490 return switch (tree.nodeTag(node)) {2459 return switch (tree.nodeTag(node)) {
2491 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),2460 .call, .call_comma => tree.callFull(node),
2492 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),2461 .call_one, .call_one_comma => tree.callOne(buffer, node),
2493 else => null,2462 else => null,
2494 };2463 };
2495}2464}
...@@ -2882,7 +2851,6 @@ pub const full = struct {...@@ -2882,7 +2851,6 @@ pub const full = struct {
28822851
2883 pub const Call = struct {2852 pub const Call = struct {
2884 ast: Components,2853 ast: Components,
2885 async_token: ?TokenIndex,
28862854
2887 pub const Components = struct {2855 pub const Components = struct {
2888 lparen: TokenIndex,2856 lparen: TokenIndex,
...@@ -3301,8 +3269,6 @@ pub const Node = struct {...@@ -3301,8 +3269,6 @@ pub const Node = struct {
3301 address_of,3269 address_of,
3302 /// `try expr`. The `main_token` field is the `try` token.3270 /// `try expr`. The `main_token` field is the `try` token.
3303 @"try",3271 @"try",
3304 /// `await expr`. The `main_token` field is the `await` token.
3305 @"await",
3306 /// `?expr`. The `main_token` field is the `?` token.3272 /// `?expr`. The `main_token` field is the `?` token.
3307 optional_type,3273 optional_type,
3308 /// `[lhs]rhs`. The `main_token` field is the `[` token.3274 /// `[lhs]rhs`. The `main_token` field is the `[` token.
...@@ -3498,17 +3464,6 @@ pub const Node = struct {...@@ -3498,17 +3464,6 @@ pub const Node = struct {
3498 /// Same as `call_one` except there is known to be a trailing comma3464 /// Same as `call_one` except there is known to be a trailing comma
3499 /// before the final rparen.3465 /// before the final rparen.
3500 call_one_comma,3466 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,
3512 /// `a(b, c, d)`.3467 /// `a(b, c, d)`.
3513 ///3468 ///
3514 /// The `data` field is a `.node_and_extra`:3469 /// The `data` field is a `.node_and_extra`:
...@@ -3521,18 +3476,6 @@ pub const Node = struct {...@@ -3521,18 +3476,6 @@ pub const Node = struct {
3521 /// Same as `call` except there is known to be a trailing comma before3476 /// Same as `call` except there is known to be a trailing comma before
3522 /// the final rparen.3477 /// the final rparen.
3523 call_comma,3478 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,
3536 /// `switch(a) {}`.3479 /// `switch(a) {}`.
3537 ///3480 ///
3538 /// The `data` field is a `.node_and_extra`:3481 /// 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...@@ -510,12 +510,8 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
510 .number_literal,510 .number_literal,
511 .call,511 .call,
512 .call_comma,512 .call_comma,
513 .async_call,
514 .async_call_comma,
515 .call_one,513 .call_one,
516 .call_one_comma,514 .call_one_comma,
517 .async_call_one,
518 .async_call_one_comma,
519 .unreachable_literal,515 .unreachable_literal,
520 .@"return",516 .@"return",
521 .@"if",517 .@"if",
...@@ -547,7 +543,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins...@@ -547,7 +543,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
547 .merge_error_sets,543 .merge_error_sets,
548 .switch_range,544 .switch_range,
549 .for_range,545 .for_range,
550 .@"await",
551 .bit_not,546 .bit_not,
552 .negation,547 .negation,
553 .negation_wrap,548 .negation_wrap,
...@@ -836,12 +831,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -836,12 +831,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
836831
837 .call_one,832 .call_one,
838 .call_one_comma,833 .call_one_comma,
839 .async_call_one,
840 .async_call_one_comma,
841 .call,834 .call,
842 .call_comma,835 .call_comma,
843 .async_call,
844 .async_call_comma,
845 => {836 => {
846 var buf: [1]Ast.Node.Index = undefined;837 var buf: [1]Ast.Node.Index = undefined;
847 return callExpr(gz, scope, ri, .none, node, tree.fullCall(&buf, node).?);838 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...@@ -1114,7 +1105,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11141105
1115 .@"nosuspend" => return nosuspendExpr(gz, scope, ri, node),1106 .@"nosuspend" => return nosuspendExpr(gz, scope, ri, node),
1116 .@"suspend" => return suspendExpr(gz, scope, node),1107 .@"suspend" => return suspendExpr(gz, scope, node),
1117 .@"await" => return awaitExpr(gz, scope, ri, node),
1118 .@"resume" => return resumeExpr(gz, scope, ri, node),1108 .@"resume" => return resumeExpr(gz, scope, ri, node),
11191109
1120 .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),1110 .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),
...@@ -1259,33 +1249,6 @@ fn suspendExpr(...@@ -1259,33 +1249,6 @@ fn suspendExpr(
1259 return suspend_inst.toRef();1249 return suspend_inst.toRef();
1260}1250}
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
1289fn resumeExpr(1252fn resumeExpr(
1290 gz: *GenZir,1253 gz: *GenZir,
1291 scope: *Scope,1254 scope: *Scope,
...@@ -2853,7 +2816,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2853,7 +2816,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2853 .tag_name,2816 .tag_name,
2854 .type_name,2817 .type_name,
2855 .frame_type,2818 .frame_type,
2856 .frame_size,
2857 .int_from_float,2819 .int_from_float,
2858 .float_from_int,2820 .float_from_int,
2859 .ptr_from_int,2821 .ptr_from_int,
...@@ -2887,7 +2849,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2887,7 +2849,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2887 .min,2849 .min,
2888 .c_import,2850 .c_import,
2889 .@"resume",2851 .@"resume",
2890 .@"await",
2891 .ret_err_value_code,2852 .ret_err_value_code,
2892 .ret_ptr,2853 .ret_ptr,
2893 .ret_type,2854 .ret_type,
...@@ -9501,7 +9462,6 @@ fn builtinCall(...@@ -9501,7 +9462,6 @@ fn builtinCall(
9501 .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name),9462 .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name),
9502 .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name),9463 .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name),
9503 .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type),9464 .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
9506 .int_from_float => return typeCast(gz, scope, ri, node, params[0], .int_from_float, builtin_name),9466 .int_from_float => return typeCast(gz, scope, ri, node, params[0], .int_from_float, builtin_name),
9507 .float_from_int => return typeCast(gz, scope, ri, node, params[0], .float_from_int, builtin_name),9467 .float_from_int => return typeCast(gz, scope, ri, node, params[0], .float_from_int, builtin_name),
...@@ -9767,16 +9727,6 @@ fn builtinCall(...@@ -9767,16 +9727,6 @@ fn builtinCall(
9767 });9727 });
9768 return rvalue(gz, ri, result, node);9728 return rvalue(gz, ri, result, node);
9769 },9729 },
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 },
9780 .Vector => {9730 .Vector => {
9781 const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{9731 const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
9782 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .type),9732 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .type),
...@@ -10175,11 +10125,8 @@ fn callExpr(...@@ -10175,11 +10125,8 @@ fn callExpr(
1017510125
10176 const callee = try calleeExpr(gz, scope, ri.rl, override_decl_literal_type, call.ast.fn_expr);10126 const callee = try calleeExpr(gz, scope, ri.rl, override_decl_literal_type, call.ast.fn_expr);
10177 const modifier: std.builtin.CallModifier = blk: {10127 const modifier: std.builtin.CallModifier = blk: {
10178 if (call.async_token != null) {
10179 break :blk .async_kw;
10180 }
10181 if (gz.nosuspend_node != .none) {10128 if (gz.nosuspend_node != .none) {
10182 break :blk .no_async;10129 break :blk .no_suspend;
10183 }10130 }
10184 break :blk .auto;10131 break :blk .auto;
10185 };10132 };
...@@ -10483,12 +10430,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10483,12 +10430,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10483 .switch_comma,10430 .switch_comma,
10484 .call_one,10431 .call_one,
10485 .call_one_comma,10432 .call_one_comma,
10486 .async_call_one,
10487 .async_call_one_comma,
10488 .call,10433 .call,
10489 .call_comma,10434 .call_comma,
10490 .async_call,
10491 .async_call_comma,
10492 => return .maybe,10435 => return .maybe,
1049310436
10494 .@"return",10437 .@"return",
...@@ -10613,7 +10556,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10613,7 +10556,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1061310556
10614 // Forward the question to the LHS sub-expression.10557 // Forward the question to the LHS sub-expression.
10615 .@"try",10558 .@"try",
10616 .@"await",
10617 .@"comptime",10559 .@"comptime",
10618 .@"nosuspend",10560 .@"nosuspend",
10619 => node = tree.nodeData(node).node,10561 => node = tree.nodeData(node).node,
...@@ -10803,12 +10745,8 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -10803,12 +10745,8 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
10803 .switch_comma,10745 .switch_comma,
10804 .call_one,10746 .call_one,
10805 .call_one_comma,10747 .call_one_comma,
10806 .async_call_one,
10807 .async_call_one_comma,
10808 .call,10748 .call,
10809 .call_comma,10749 .call_comma,
10810 .async_call,
10811 .async_call_comma,
10812 .block_two,10750 .block_two,
10813 .block_two_semicolon,10751 .block_two_semicolon,
10814 .block,10752 .block,
...@@ -10826,7 +10764,6 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -10826,7 +10764,6 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1082610764
10827 // Forward the question to the LHS sub-expression.10765 // Forward the question to the LHS sub-expression.
10828 .@"try",10766 .@"try",
10829 .@"await",
10830 .@"comptime",10767 .@"comptime",
10831 .@"nosuspend",10768 .@"nosuspend",
10832 => node = tree.nodeData(node).node,10769 => node = tree.nodeData(node).node,
...@@ -11047,12 +10984,8 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -11047,12 +10984,8 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
11047 .switch_comma,10984 .switch_comma,
11048 .call_one,10985 .call_one,
11049 .call_one_comma,10986 .call_one_comma,
11050 .async_call_one,
11051 .async_call_one_comma,
11052 .call,10987 .call,
11053 .call_comma,10988 .call_comma,
11054 .async_call,
11055 .async_call_comma,
11056 .block_two,10989 .block_two,
11057 .block_two_semicolon,10990 .block_two_semicolon,
11058 .block,10991 .block,
...@@ -11079,7 +11012,6 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -11079,7 +11012,6 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1107911012
11080 // Forward the question to the LHS sub-expression.11013 // Forward the question to the LHS sub-expression.
11081 .@"try",11014 .@"try",
11082 .@"await",
11083 .@"comptime",11015 .@"comptime",
11084 .@"nosuspend",11016 .@"nosuspend",
11085 => node = tree.nodeData(node).node,11017 => 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...@@ -334,12 +334,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
334334
335 .call_one,335 .call_one,
336 .call_one_comma,336 .call_one_comma,
337 .async_call_one,
338 .async_call_one_comma,
339 .call,337 .call,
340 .call_comma,338 .call_comma,
341 .async_call,
342 .async_call_comma,
343 => {339 => {
344 var buf: [1]Ast.Node.Index = undefined;340 var buf: [1]Ast.Node.Index = undefined;
345 const full = tree.fullCall(&buf, node).?;341 const full = tree.fullCall(&buf, node).?;
...@@ -353,11 +349,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -353,11 +349,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
353 .call,349 .call,
354 .call_comma,350 .call_comma,
355 => false, // TODO: once function calls are passed result locations this will change351 => 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
361 else => unreachable,352 else => unreachable,
362 };353 };
363 },354 },
...@@ -503,7 +494,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -503,7 +494,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
503 return false;494 return false;
504 },495 },
505 .@"try",496 .@"try",
506 .@"await",
507 .@"nosuspend",497 .@"nosuspend",
508 => return astrl.expr(tree.nodeData(node).node, block, ri),498 => return astrl.expr(tree.nodeData(node).node, block, ri),
509 .grouped_expression,499 .grouped_expression,
...@@ -948,7 +938,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -948,7 +938,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
948 .tag_name,938 .tag_name,
949 .type_name,939 .type_name,
950 .Frame,940 .Frame,
951 .frame_size,
952 .int_from_float,941 .int_from_float,
953 .float_from_int,942 .float_from_int,
954 .ptr_from_int,943 .ptr_from_int,
...@@ -1079,13 +1068,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -1079,13 +1068,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
1079 _ = try astrl.expr(args[3], block, ResultInfo.none);1068 _ = try astrl.expr(args[3], block, ResultInfo.none);
1080 return false;1069 return false;
1081 },1070 },
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 },
1089 .Vector => {1071 .Vector => {
1090 _ = try astrl.expr(args[0], block, ResultInfo.type_only);1072 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1091 _ = try astrl.expr(args[1], block, ResultInfo.type_only);1073 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
lib/std/zig/BuiltinFn.zig-16
...@@ -4,7 +4,6 @@ pub const Tag = enum {...@@ -4,7 +4,6 @@ pub const Tag = enum {
4 align_cast,4 align_cast,
5 align_of,5 align_of,
6 as,6 as,
7 async_call,
8 atomic_load,7 atomic_load,
9 atomic_rmw,8 atomic_rmw,
10 atomic_store,9 atomic_store,
...@@ -55,7 +54,6 @@ pub const Tag = enum {...@@ -55,7 +54,6 @@ pub const Tag = enum {
55 frame,54 frame,
56 Frame,55 Frame,
57 frame_address,56 frame_address,
58 frame_size,
59 has_decl,57 has_decl,
60 has_field,58 has_field,
61 import,59 import,
...@@ -184,13 +182,6 @@ pub const list = list: {...@@ -184,13 +182,6 @@ pub const list = list: {
184 .param_count = 2,182 .param_count = 2,
185 },183 },
186 },184 },
187 .{
188 "@asyncCall",
189 .{
190 .tag = .async_call,
191 .param_count = 4,
192 },
193 },
194 .{185 .{
195 "@atomicLoad",186 "@atomicLoad",
196 .{187 .{
...@@ -550,13 +541,6 @@ pub const list = list: {...@@ -550,13 +541,6 @@ pub const list = list: {
550 .illegal_outside_function = true,541 .illegal_outside_function = true,
551 },542 },
552 },543 },
553 .{
554 "@frameSize",
555 .{
556 .tag = .frame_size,
557 .param_count = 1,
558 },
559 },
560 .{544 .{
561 "@hasDecl",545 "@hasDecl",
562 .{546 .{
lib/std/zig/Parse.zig+1-53
...@@ -1688,7 +1688,6 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index {...@@ -1688,7 +1688,6 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index {
1688/// / MINUSPERCENT1688/// / MINUSPERCENT
1689/// / AMPERSAND1689/// / AMPERSAND
1690/// / KEYWORD_try1690/// / KEYWORD_try
1691/// / KEYWORD_await
1692fn parsePrefixExpr(p: *Parse) Error!?Node.Index {1691fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
1693 const tag: Node.Tag = switch (p.tokenTag(p.tok_i)) {1692 const tag: Node.Tag = switch (p.tokenTag(p.tok_i)) {
1694 .bang => .bool_not,1693 .bang => .bool_not,
...@@ -1697,7 +1696,6 @@ fn parsePrefixExpr(p: *Parse) Error!?Node.Index {...@@ -1697,7 +1696,6 @@ fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
1697 .minus_percent => .negation_wrap,1696 .minus_percent => .negation_wrap,
1698 .ampersand => .address_of,1697 .ampersand => .address_of,
1699 .keyword_try => .@"try",1698 .keyword_try => .@"try",
1700 .keyword_await => .@"await",
1701 else => return p.parsePrimaryExpr(),1699 else => return p.parsePrimaryExpr(),
1702 };1700 };
1703 return try p.addNode(.{1701 return try p.addNode(.{
...@@ -2385,62 +2383,12 @@ fn parseErrorUnionExpr(p: *Parse) !?Node.Index {...@@ -2385,62 +2383,12 @@ fn parseErrorUnionExpr(p: *Parse) !?Node.Index {
2385}2383}
23862384
2387/// SuffixExpr2385/// SuffixExpr
2388/// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments2386/// <- PrimaryTypeExpr (SuffixOp / FnCallArguments)*
2389/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
2390///2387///
2391/// FnCallArguments <- LPAREN ExprList RPAREN2388/// FnCallArguments <- LPAREN ExprList RPAREN
2392///2389///
2393/// ExprList <- (Expr COMMA)* Expr?2390/// ExprList <- (Expr COMMA)* Expr?
2394fn parseSuffixExpr(p: *Parse) !?Node.Index {2391fn 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
2444 var res = try p.parsePrimaryTypeExpr() orelse return null;2392 var res = try p.parsePrimaryTypeExpr() orelse return null;
2445 while (true) {2393 while (true) {
2446 const opt_suffix_op = try p.parseSuffixOp(res);2394 const opt_suffix_op = try p.parseSuffixOp(res);
lib/std/zig/Zir.zig-26
...@@ -899,8 +899,6 @@ pub const Inst = struct {...@@ -899,8 +899,6 @@ pub const Inst = struct {
899 type_name,899 type_name,
900 /// Implement builtin `@Frame`. Uses `un_node`.900 /// Implement builtin `@Frame`. Uses `un_node`.
901 frame_type,901 frame_type,
902 /// Implement builtin `@frameSize`. Uses `un_node`.
903 frame_size,
904902
905 /// Implements the `@intFromFloat` builtin.903 /// Implements the `@intFromFloat` builtin.
906 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.904 /// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
...@@ -1044,7 +1042,6 @@ pub const Inst = struct {...@@ -1044,7 +1042,6 @@ pub const Inst = struct {
10441042
1045 /// Implements `resume` syntax. Uses `un_node` field.1043 /// Implements `resume` syntax. Uses `un_node` field.
1046 @"resume",1044 @"resume",
1047 @"await",
10481045
1049 /// A defer statement.1046 /// A defer statement.
1050 /// Uses the `defer` union field.1047 /// Uses the `defer` union field.
...@@ -1241,7 +1238,6 @@ pub const Inst = struct {...@@ -1241,7 +1238,6 @@ pub const Inst = struct {
1241 .tag_name,1238 .tag_name,
1242 .type_name,1239 .type_name,
1243 .frame_type,1240 .frame_type,
1244 .frame_size,
1245 .int_from_float,1241 .int_from_float,
1246 .float_from_int,1242 .float_from_int,
1247 .ptr_from_int,1243 .ptr_from_int,
...@@ -1279,7 +1275,6 @@ pub const Inst = struct {...@@ -1279,7 +1275,6 @@ pub const Inst = struct {
1279 .min,1275 .min,
1280 .c_import,1276 .c_import,
1281 .@"resume",1277 .@"resume",
1282 .@"await",
1283 .ret_err_value_code,1278 .ret_err_value_code,
1284 .extended,1279 .extended,
1285 .ret_ptr,1280 .ret_ptr,
...@@ -1526,7 +1521,6 @@ pub const Inst = struct {...@@ -1526,7 +1521,6 @@ pub const Inst = struct {
1526 .tag_name,1521 .tag_name,
1527 .type_name,1522 .type_name,
1528 .frame_type,1523 .frame_type,
1529 .frame_size,
1530 .int_from_float,1524 .int_from_float,
1531 .float_from_int,1525 .float_from_int,
1532 .ptr_from_int,1526 .ptr_from_int,
...@@ -1560,7 +1554,6 @@ pub const Inst = struct {...@@ -1560,7 +1554,6 @@ pub const Inst = struct {
1560 .min,1554 .min,
1561 .c_import,1555 .c_import,
1562 .@"resume",1556 .@"resume",
1563 .@"await",
1564 .ret_err_value_code,1557 .ret_err_value_code,
1565 .@"break",1558 .@"break",
1566 .break_inline,1559 .break_inline,
...@@ -1791,7 +1784,6 @@ pub const Inst = struct {...@@ -1791,7 +1784,6 @@ pub const Inst = struct {
1791 .tag_name = .un_node,1784 .tag_name = .un_node,
1792 .type_name = .un_node,1785 .type_name = .un_node,
1793 .frame_type = .un_node,1786 .frame_type = .un_node,
1794 .frame_size = .un_node,
17951787
1796 .int_from_float = .pl_node,1788 .int_from_float = .pl_node,
1797 .float_from_int = .pl_node,1789 .float_from_int = .pl_node,
...@@ -1852,7 +1844,6 @@ pub const Inst = struct {...@@ -1852,7 +1844,6 @@ pub const Inst = struct {
1852 .make_ptr_const = .un_node,1844 .make_ptr_const = .un_node,
18531845
1854 .@"resume" = .un_node,1846 .@"resume" = .un_node,
1855 .@"await" = .un_node,
18561847
1857 .@"defer" = .@"defer",1848 .@"defer" = .@"defer",
1858 .defer_err_code = .defer_err_code,1849 .defer_err_code = .defer_err_code,
...@@ -2016,8 +2007,6 @@ pub const Inst = struct {...@@ -2016,8 +2007,6 @@ pub const Inst = struct {
2016 /// Implements the `@errorCast` builtin.2007 /// Implements the `@errorCast` builtin.
2017 /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.2008 /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.
2018 error_cast,2009 error_cast,
2019 /// `operand` is payload index to `UnNode`.
2020 await_nosuspend,
2021 /// Implements `@breakpoint`.2010 /// Implements `@breakpoint`.
2022 /// `operand` is `src_node: Ast.Node.Offset`.2011 /// `operand` is `src_node: Ast.Node.Offset`.
2023 breakpoint,2012 breakpoint,
...@@ -2038,9 +2027,6 @@ pub const Inst = struct {...@@ -2038,9 +2027,6 @@ pub const Inst = struct {
2038 /// `operand` is payload index to `Reify`.2027 /// `operand` is payload index to `Reify`.
2039 /// `small` contains `NameStrategy`.2028 /// `small` contains `NameStrategy`.
2040 reify,2029 reify,
2041 /// Implements the `@asyncCall` builtin.
2042 /// `operand` is payload index to `AsyncCall`.
2043 builtin_async_call,
2044 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.2030 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
2045 /// `small` 0=>weak 1=>strong2031 /// `small` 0=>weak 1=>strong
2046 /// `operand` is payload index to `Cmpxchg`.2032 /// `operand` is payload index to `Cmpxchg`.
...@@ -3771,14 +3757,6 @@ pub const Inst = struct {...@@ -3771,14 +3757,6 @@ pub const Inst = struct {
3771 b: Ref,3757 b: Ref,
3772 };3758 };
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
3782 /// Trailing: inst: Index // for every body_len3760 /// Trailing: inst: Index // for every body_len
3783 pub const Param = struct {3761 pub const Param = struct {
3784 /// Null-terminated string index.3762 /// Null-terminated string index.
...@@ -4297,7 +4275,6 @@ fn findTrackableInner(...@@ -4297,7 +4275,6 @@ fn findTrackableInner(
4297 .tag_name,4275 .tag_name,
4298 .type_name,4276 .type_name,
4299 .frame_type,4277 .frame_type,
4300 .frame_size,
4301 .int_from_float,4278 .int_from_float,
4302 .float_from_int,4279 .float_from_int,
4303 .ptr_from_int,4280 .ptr_from_int,
...@@ -4337,7 +4314,6 @@ fn findTrackableInner(...@@ -4337,7 +4314,6 @@ fn findTrackableInner(
4337 .resolve_inferred_alloc,4314 .resolve_inferred_alloc,
4338 .make_ptr_const,4315 .make_ptr_const,
4339 .@"resume",4316 .@"resume",
4340 .@"await",
4341 .save_err_ret_index,4317 .save_err_ret_index,
4342 .restore_err_ret_index_unconditional,4318 .restore_err_ret_index_unconditional,
4343 .restore_err_ret_index_fn_entry,4319 .restore_err_ret_index_fn_entry,
...@@ -4380,14 +4356,12 @@ fn findTrackableInner(...@@ -4380,14 +4356,12 @@ fn findTrackableInner(
4380 .prefetch,4356 .prefetch,
4381 .set_float_mode,4357 .set_float_mode,
4382 .error_cast,4358 .error_cast,
4383 .await_nosuspend,
4384 .breakpoint,4359 .breakpoint,
4385 .disable_instrumentation,4360 .disable_instrumentation,
4386 .disable_intrinsics,4361 .disable_intrinsics,
4387 .select,4362 .select,
4388 .int_from_error,4363 .int_from_error,
4389 .error_from_int,4364 .error_from_int,
4390 .builtin_async_call,
4391 .cmpxchg,4365 .cmpxchg,
4392 .c_va_arg,4366 .c_va_arg,
4393 .c_va_copy,4367 .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...@@ -204,12 +204,8 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
204204
205 .call_one,205 .call_one,
206 .call_one_comma,206 .call_one_comma,
207 .async_call_one,
208 .async_call_one_comma,
209 .call,207 .call,
210 .call_comma,208 .call_comma,
211 .async_call,
212 .async_call_comma,
213 .@"return",209 .@"return",
214 .if_simple,210 .if_simple,
215 .@"if",211 .@"if",
...@@ -226,7 +222,6 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -226,7 +222,6 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
226 .switch_comma,222 .switch_comma,
227 .@"nosuspend",223 .@"nosuspend",
228 .@"suspend",224 .@"suspend",
229 .@"await",
230 .@"resume",225 .@"resume",
231 .@"try",226 .@"try",
232 .unreachable_literal,227 .unreachable_literal,
lib/std/zig/parser_test.zig-76
...@@ -341,15 +341,6 @@ test "zig fmt: nosuspend block" {...@@ -341,15 +341,6 @@ test "zig fmt: nosuspend block" {
341 );341 );
342}342}
343343
344test "zig fmt: nosuspend await" {
345 try testCanonical(
346 \\fn foo() void {
347 \\ x = nosuspend await y;
348 \\}
349 \\
350 );
351}
352
353test "zig fmt: container declaration, single line" {344test "zig fmt: container declaration, single line" {
354 try testCanonical(345 try testCanonical(
355 \\const X = struct { foo: i32 };346 \\const X = struct { foo: i32 };
...@@ -1093,18 +1084,6 @@ test "zig fmt: block in slice expression" {...@@ -1093,18 +1084,6 @@ test "zig fmt: block in slice expression" {
1093 );1084 );
1094}1085}
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
1108test "zig fmt: whitespace fixes" {1087test "zig fmt: whitespace fixes" {
1109 try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",1088 try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",
1110 \\test "" {1089 \\test "" {
...@@ -1549,17 +1528,6 @@ test "zig fmt: spaces around slice operator" {...@@ -1549,17 +1528,6 @@ test "zig fmt: spaces around slice operator" {
1549 );1528 );
1550}1529}
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
1563test "zig fmt: 2nd arg multiline string" {1531test "zig fmt: 2nd arg multiline string" {
1564 try testCanonical(1532 try testCanonical(
1565 \\comptime {1533 \\comptime {
...@@ -3946,27 +3914,6 @@ test "zig fmt: inline asm" {...@@ -3946,27 +3914,6 @@ test "zig fmt: inline asm" {
3946 );3914 );
3947}3915}
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
3970test "zig fmt: nosuspend" {3917test "zig fmt: nosuspend" {
3971 try testCanonical(3918 try testCanonical(
3972 \\const a = nosuspend foo();3919 \\const a = nosuspend foo();
...@@ -6181,29 +6128,6 @@ test "recovery: missing return type" {...@@ -6181,29 +6128,6 @@ test "recovery: missing return type" {
6181 });6128 });
6182}6129}
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
6207test "recovery: invalid extern/inline" {6131test "recovery: invalid extern/inline" {
6208 try testError(6132 try testError(
6209 \\inline test "" { a & b; }6133 \\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 {...@@ -591,7 +591,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
591591
592 .@"try",592 .@"try",
593 .@"resume",593 .@"resume",
594 .@"await",
595 => {594 => {
596 try renderToken(r, tree.nodeMainToken(node), .space);595 try renderToken(r, tree.nodeMainToken(node), .space);
597 return renderExpression(r, tree.nodeData(node).node, space);596 return renderExpression(r, tree.nodeData(node).node, space);
...@@ -635,12 +634,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -635,12 +634,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
635634
636 .call_one,635 .call_one,
637 .call_one_comma,636 .call_one_comma,
638 .async_call_one,
639 .async_call_one_comma,
640 .call,637 .call,
641 .call_comma,638 .call_comma,
642 .async_call,
643 .async_call_comma,
644 => {639 => {
645 var buf: [1]Ast.Node.Index = undefined;640 var buf: [1]Ast.Node.Index = undefined;
646 return renderCall(r, tree.fullCall(&buf, node).?, space);641 return renderCall(r, tree.fullCall(&buf, node).?, space);
...@@ -2551,9 +2546,6 @@ fn renderCall(...@@ -2551,9 +2546,6 @@ fn renderCall(
2551 call: Ast.full.Call,2546 call: Ast.full.Call,
2552 space: Space,2547 space: Space,
2553) Error!void {2548) Error!void {
2554 if (call.async_token) |async_token| {
2555 try renderToken(r, async_token, .space);
2556 }
2557 try renderExpression(r, call.ast.fn_expr, .none);2549 try renderExpression(r, call.ast.fn_expr, .none);
2558 try renderParamList(r, call.ast.lparen, call.ast.params, space);2550 try renderParamList(r, call.ast.lparen, call.ast.params, space);
2559}2551}
lib/std/zig/tokenizer.zig-6
...@@ -17,8 +17,6 @@ pub const Token = struct {...@@ -17,8 +17,6 @@ pub const Token = struct {
17 .{ "anyframe", .keyword_anyframe },17 .{ "anyframe", .keyword_anyframe },
18 .{ "anytype", .keyword_anytype },18 .{ "anytype", .keyword_anytype },
19 .{ "asm", .keyword_asm },19 .{ "asm", .keyword_asm },
20 .{ "async", .keyword_async },
21 .{ "await", .keyword_await },
22 .{ "break", .keyword_break },20 .{ "break", .keyword_break },
23 .{ "callconv", .keyword_callconv },21 .{ "callconv", .keyword_callconv },
24 .{ "catch", .keyword_catch },22 .{ "catch", .keyword_catch },
...@@ -146,8 +144,6 @@ pub const Token = struct {...@@ -146,8 +144,6 @@ pub const Token = struct {
146 keyword_anyframe,144 keyword_anyframe,
147 keyword_anytype,145 keyword_anytype,
148 keyword_asm,146 keyword_asm,
149 keyword_async,
150 keyword_await,
151 keyword_break,147 keyword_break,
152 keyword_callconv,148 keyword_callconv,
153 keyword_catch,149 keyword_catch,
...@@ -273,8 +269,6 @@ pub const Token = struct {...@@ -273,8 +269,6 @@ pub const Token = struct {
273 .keyword_anyframe => "anyframe",269 .keyword_anyframe => "anyframe",
274 .keyword_anytype => "anytype",270 .keyword_anytype => "anytype",
275 .keyword_asm => "asm",271 .keyword_asm => "asm",
276 .keyword_async => "async",
277 .keyword_await => "await",
278 .keyword_break => "break",272 .keyword_break => "break",
279 .keyword_callconv => "callconv",273 .keyword_callconv => "callconv",
280 .keyword_catch => "catch",274 .keyword_catch => "catch",
src/Sema.zig+3-54
...@@ -1280,7 +1280,6 @@ fn analyzeBodyInner(...@@ -1280,7 +1280,6 @@ fn analyzeBodyInner(
1280 .tag_name => try sema.zirTagName(block, inst),1280 .tag_name => try sema.zirTagName(block, inst),
1281 .type_name => try sema.zirTypeName(block, inst),1281 .type_name => try sema.zirTypeName(block, inst),
1282 .frame_type => try sema.zirFrameType(block, inst),1282 .frame_type => try sema.zirFrameType(block, inst),
1283 .frame_size => try sema.zirFrameSize(block, inst),
1284 .int_from_float => try sema.zirIntFromFloat(block, inst),1283 .int_from_float => try sema.zirIntFromFloat(block, inst),
1285 .float_from_int => try sema.zirFloatFromInt(block, inst),1284 .float_from_int => try sema.zirFloatFromInt(block, inst),
1286 .ptr_from_int => try sema.zirPtrFromInt(block, inst),1285 .ptr_from_int => try sema.zirPtrFromInt(block, inst),
...@@ -1302,7 +1301,6 @@ fn analyzeBodyInner(...@@ -1302,7 +1301,6 @@ fn analyzeBodyInner(
1302 .mul_add => try sema.zirMulAdd(block, inst),1301 .mul_add => try sema.zirMulAdd(block, inst),
1303 .builtin_call => try sema.zirBuiltinCall(block, inst),1302 .builtin_call => try sema.zirBuiltinCall(block, inst),
1304 .@"resume" => try sema.zirResume(block, inst),1303 .@"resume" => try sema.zirResume(block, inst),
1305 .@"await" => try sema.zirAwait(block, inst),
1306 .for_len => try sema.zirForLen(block, inst),1304 .for_len => try sema.zirForLen(block, inst),
1307 .validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst),1305 .validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst),
1308 .opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst),1306 .opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst),
...@@ -1410,12 +1408,10 @@ fn analyzeBodyInner(...@@ -1410,12 +1408,10 @@ fn analyzeBodyInner(
1410 .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended),1408 .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended),
1411 .prefetch => try sema.zirPrefetch( block, extended),1409 .prefetch => try sema.zirPrefetch( block, extended),
1412 .error_cast => try sema.zirErrorCast( block, extended),1410 .error_cast => try sema.zirErrorCast( block, extended),
1413 .await_nosuspend => try sema.zirAwaitNosuspend( block, extended),
1414 .select => try sema.zirSelect( block, extended),1411 .select => try sema.zirSelect( block, extended),
1415 .int_from_error => try sema.zirIntFromError( block, extended),1412 .int_from_error => try sema.zirIntFromError( block, extended),
1416 .error_from_int => try sema.zirErrorFromInt( block, extended),1413 .error_from_int => try sema.zirErrorFromInt( block, extended),
1417 .reify => try sema.zirReify( block, extended, inst),1414 .reify => try sema.zirReify( block, extended, inst),
1418 .builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended),
1419 .cmpxchg => try sema.zirCmpxchg( block, extended),1415 .cmpxchg => try sema.zirCmpxchg( block, extended),
1420 .c_va_arg => try sema.zirCVaArg( block, extended),1416 .c_va_arg => try sema.zirCVaArg( block, extended),
1421 .c_va_copy => try sema.zirCVaCopy( block, extended),1417 .c_va_copy => try sema.zirCVaCopy( block, extended),
...@@ -7653,10 +7649,6 @@ fn analyzeCall(...@@ -7653,10 +7649,6 @@ fn analyzeCall(
7653 const ip = &zcu.intern_pool;7649 const ip = &zcu.intern_pool;
7654 const arena = sema.arena;7650 const arena = sema.arena;
76557651
7656 if (modifier == .async_kw) {
7657 return sema.failWithUseOfAsync(block, call_src);
7658 }
7659
7660 const maybe_func_inst = try sema.funcDeclSrcInst(callee);7652 const maybe_func_inst = try sema.funcDeclSrcInst(callee);
7661 const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{7653 const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{
7662 .base_node_inst = fn_decl_inst,7654 .base_node_inst = fn_decl_inst,
...@@ -8048,14 +8040,13 @@ fn analyzeCall(...@@ -8048,14 +8040,13 @@ fn analyzeCall(
8048 }8040 }
80498041
8050 const call_tag: Air.Inst.Tag = switch (modifier) {8042 const call_tag: Air.Inst.Tag = switch (modifier) {
8051 .auto, .no_async => .call,8043 .auto, .no_suspend => .call,
8052 .never_tail => .call_never_tail,8044 .never_tail => .call_never_tail,
8053 .never_inline => .call_never_inline,8045 .never_inline => .call_never_inline,
8054 .always_tail => .call_always_tail,8046 .always_tail => .call_always_tail,
80558047
8056 .always_inline,8048 .always_inline,
8057 .compile_time,8049 .compile_time,
8058 .async_kw,
8059 => unreachable,8050 => unreachable,
8060 };8051 };
80618052
...@@ -22133,12 +22124,6 @@ fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -22133,12 +22124,6 @@ fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
22133 return sema.failWithUseOfAsync(block, src);22124 return sema.failWithUseOfAsync(block, src);
22134}22125}
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
22142fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {22127fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
22143 const pt = sema.pt;22128 const pt = sema.pt;
22144 const zcu = pt.zcu;22129 const zcu = pt.zcu;
...@@ -24776,14 +24761,14 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -24776,14 +24761,14 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
24776 var modifier = try sema.interpretBuiltinType(block, modifier_src, modifier_val, std.builtin.CallModifier);24761 var modifier = try sema.interpretBuiltinType(block, modifier_src, modifier_val, std.builtin.CallModifier);
24777 switch (modifier) {24762 switch (modifier) {
24778 // These can be upgraded to comptime or nosuspend calls.24763 // These can be upgraded to comptime or nosuspend calls.
24779 .auto, .never_tail, .no_async => {24764 .auto, .never_tail, .no_suspend => {
24780 if (block.isComptime()) {24765 if (block.isComptime()) {
24781 if (modifier == .never_tail) {24766 if (modifier == .never_tail) {
24782 return sema.fail(block, modifier_src, "unable to perform 'never_tail' call at compile-time", .{});24767 return sema.fail(block, modifier_src, "unable to perform 'never_tail' call at compile-time", .{});
24783 }24768 }
24784 modifier = .compile_time;24769 modifier = .compile_time;
24785 } else if (extra.flags.is_nosuspend) {24770 } else if (extra.flags.is_nosuspend) {
24786 modifier = .no_async;24771 modifier = .no_suspend;
24787 }24772 }
24788 },24773 },
24789 // These can be upgraded to comptime. nosuspend bit can be safely ignored.24774 // 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...@@ -24801,14 +24786,6 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
24801 modifier = .compile_time;24786 modifier = .compile_time;
24802 }24787 }
24803 },24788 },
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 },
24812 .never_inline => {24789 .never_inline => {
24813 if (block.isComptime()) {24790 if (block.isComptime()) {
24814 return sema.fail(block, modifier_src, "unable to perform 'never_inline' call at compile-time", .{});24791 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...@@ -25797,40 +25774,12 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25797 });25774 });
25798}25775}
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
25806fn zirResume(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {25777fn zirResume(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
25807 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;25778 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
25808 const src = block.nodeOffset(inst_data.src_node);25779 const src = block.nodeOffset(inst_data.src_node);
25809 return sema.failWithUseOfAsync(block, src);25780 return sema.failWithUseOfAsync(block, src);
25810}25781}
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
25834fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {25783fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
25835 const tracy = trace(@src());25784 const tracy = trace(@src());
25836 defer tracy.end();25785 defer tracy.end();
src/Zcu.zig-4
...@@ -1443,12 +1443,8 @@ pub const SrcLoc = struct {...@@ -1443,12 +1443,8 @@ pub const SrcLoc = struct {
1443 .field_access => tree.nodeData(node).node_and_token[1],1443 .field_access => tree.nodeData(node).node_and_token[1],
1444 .call_one,1444 .call_one,
1445 .call_one_comma,1445 .call_one_comma,
1446 .async_call_one,
1447 .async_call_one_comma,
1448 .call,1446 .call,
1449 .call_comma,1447 .call_comma,
1450 .async_call,
1451 .async_call_comma,
1452 => blk: {1448 => blk: {
1453 const full = tree.fullCall(&buf, node).?;1449 const full = tree.fullCall(&buf, node).?;
1454 break :blk tree.lastToken(full.ast.fn_expr);1450 break :blk tree.lastToken(full.ast.fn_expr);
src/codegen/llvm.zig+2-2
...@@ -5273,7 +5273,7 @@ pub const FuncGen = struct {...@@ -5273,7 +5273,7 @@ pub const FuncGen = struct {
5273 switch (modifier) {5273 switch (modifier) {
5274 .auto, .always_tail => {},5274 .auto, .always_tail => {},
5275 .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),5275 .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,
5277 }5277 }
52785278
5279 const ret_ptr = if (!sret) null else blk: {5279 const ret_ptr = if (!sret) null else blk: {
...@@ -5488,7 +5488,7 @@ pub const FuncGen = struct {...@@ -5488,7 +5488,7 @@ pub const FuncGen = struct {
5488 .auto, .never_inline => .normal,5488 .auto, .never_inline => .normal,
5489 .never_tail => .notail,5489 .never_tail => .notail,
5490 .always_tail => .musttail,5490 .always_tail => .musttail,
5491 .async_kw, .no_async, .always_inline, .compile_time => unreachable,5491 .no_suspend, .always_inline, .compile_time => unreachable,
5492 },5492 },
5493 toLlvmCallConvTag(fn_info.cc, target).?,5493 toLlvmCallConvTag(fn_info.cc, target).?,
5494 try attributes.finish(&o.builder),5494 try attributes.finish(&o.builder),
src/print_zir.zig-17
...@@ -261,14 +261,12 @@ const Writer = struct {...@@ -261,14 +261,12 @@ const Writer = struct {
261 .tag_name,261 .tag_name,
262 .type_name,262 .type_name,
263 .frame_type,263 .frame_type,
264 .frame_size,
265 .clz,264 .clz,
266 .ctz,265 .ctz,
267 .pop_count,266 .pop_count,
268 .byte_swap,267 .byte_swap,
269 .bit_reverse,268 .bit_reverse,
270 .@"resume",269 .@"resume",
271 .@"await",
272 .make_ptr_const,270 .make_ptr_const,
273 .validate_deref,271 .validate_deref,
274 .validate_const,272 .validate_const,
...@@ -565,7 +563,6 @@ const Writer = struct {...@@ -565,7 +563,6 @@ const Writer = struct {
565563
566 .tuple_decl => try self.writeTupleDecl(stream, extended),564 .tuple_decl => try self.writeTupleDecl(stream, extended),
567565
568 .await_nosuspend,
569 .c_undef,566 .c_undef,
570 .c_include,567 .c_include,
571 .set_float_mode,568 .set_float_mode,
...@@ -611,7 +608,6 @@ const Writer = struct {...@@ -611,7 +608,6 @@ const Writer = struct {
611 try self.writeSrcNode(stream, inst_data.node);608 try self.writeSrcNode(stream, inst_data.node);
612 },609 },
613610
614 .builtin_async_call => try self.writeBuiltinAsyncCall(stream, extended),
615 .cmpxchg => try self.writeCmpxchg(stream, extended),611 .cmpxchg => try self.writeCmpxchg(stream, extended),
616 .ptr_cast_full => try self.writePtrCastFull(stream, extended),612 .ptr_cast_full => try self.writePtrCastFull(stream, extended),
617 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),613 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
...@@ -932,19 +928,6 @@ const Writer = struct {...@@ -932,19 +928,6 @@ const Writer = struct {
932 try self.writeSrcNode(stream, extra.src_node);928 try self.writeSrcNode(stream, extra.src_node);
933 }929 }
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
948 fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {931 fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
949 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;932 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
950 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);933 const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
test/behavior.zig-2
...@@ -5,9 +5,7 @@ test {...@@ -5,9 +5,7 @@ test {
5 _ = @import("behavior/align.zig");5 _ = @import("behavior/align.zig");
6 _ = @import("behavior/alignof.zig");6 _ = @import("behavior/alignof.zig");
7 _ = @import("behavior/array.zig");7 _ = @import("behavior/array.zig");
8 _ = @import("behavior/async_fn.zig");
9 _ = @import("behavior/atomics.zig");8 _ = @import("behavior/atomics.zig");
10 _ = @import("behavior/await_struct.zig");
11 _ = @import("behavior/basic.zig");9 _ = @import("behavior/basic.zig");
12 _ = @import("behavior/bit_shifting.zig");10 _ = @import("behavior/bit_shifting.zig");
13 _ = @import("behavior/bitcast.zig");11 _ = @import("behavior/bitcast.zig");
test/behavior/align.zig-24
...@@ -425,30 +425,6 @@ test "struct field explicit alignment" {...@@ -425,30 +425,6 @@ test "struct field explicit alignment" {
425 try expect(@intFromPtr(&node.massive_byte) % 64 == 0);425 try expect(@intFromPtr(&node.massive_byte) % 64 == 0);
426}426}
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
452test "align(N) on functions" {428test "align(N) on functions" {
453 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
454 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO430 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" {...@@ -37,7 +37,7 @@ test "basic invocations" {
37 comptime {37 comptime {
38 // comptime calls with supported modifiers38 // comptime calls with supported modifiers
39 try expect(@call(.auto, foo, .{2}) == 1234);39 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);
41 try expect(@call(.always_tail, foo, .{4}) == 1234);41 try expect(@call(.always_tail, foo, .{4}) == 1234);
42 try expect(@call(.always_inline, foo, .{5}) == 1234);42 try expect(@call(.always_inline, foo, .{5}) == 1234);
43 }43 }
...@@ -45,7 +45,7 @@ test "basic invocations" {...@@ -45,7 +45,7 @@ test "basic invocations" {
45 const result = @call(.compile_time, foo, .{6}) == 1234;45 const result = @call(.compile_time, foo, .{6}) == 1234;
46 comptime assert(result);46 comptime assert(result);
47 // runtime calls of comptime-known function47 // runtime calls of comptime-known function
48 try expect(@call(.no_async, foo, .{7}) == 1234);48 try expect(@call(.no_suspend, foo, .{7}) == 1234);
49 try expect(@call(.never_tail, foo, .{8}) == 1234);49 try expect(@call(.never_tail, foo, .{8}) == 1234);
50 try expect(@call(.never_inline, foo, .{9}) == 1234);50 try expect(@call(.never_inline, foo, .{9}) == 1234);
51 // CBE does not support attributes on runtime functions51 // CBE does not support attributes on runtime functions
...@@ -53,7 +53,7 @@ test "basic invocations" {...@@ -53,7 +53,7 @@ test "basic invocations" {
53 // runtime calls of non comptime-known function53 // runtime calls of non comptime-known function
54 var alias_foo = &foo;54 var alias_foo = &foo;
55 _ = &alias_foo;55 _ = &alias_foo;
56 try expect(@call(.no_async, alias_foo, .{10}) == 1234);56 try expect(@call(.no_suspend, alias_foo, .{10}) == 1234);
57 try expect(@call(.never_tail, alias_foo, .{11}) == 1234);57 try expect(@call(.never_tail, alias_foo, .{11}) == 1234);
58 try expect(@call(.never_inline, alias_foo, .{12}) == 1234);58 try expect(@call(.never_inline, alias_foo, .{12}) == 1234);
59 }59 }
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(...@@ -710,8 +710,6 @@ fn tokenizeAndPrintRaw(
710 .keyword_align,710 .keyword_align,
711 .keyword_and,711 .keyword_and,
712 .keyword_asm,712 .keyword_asm,
713 .keyword_async,
714 .keyword_await,
715 .keyword_break,713 .keyword_break,
716 .keyword_catch,714 .keyword_catch,
717 .keyword_comptime,715 .keyword_comptime,
tools/doctest.zig-2
...@@ -653,8 +653,6 @@ fn tokenizeAndPrint(arena: Allocator, out: anytype, raw_src: []const u8) !void {...@@ -653,8 +653,6 @@ fn tokenizeAndPrint(arena: Allocator, out: anytype, raw_src: []const u8) !void {
653 .keyword_align,653 .keyword_align,
654 .keyword_and,654 .keyword_and,
655 .keyword_asm,655 .keyword_asm,
656 .keyword_async,
657 .keyword_await,
658 .keyword_break,656 .keyword_break,
659 .keyword_catch,657 .keyword_catch,
660 .keyword_comptime,658 .keyword_comptime,
tools/lldb_pretty_printers.py-2
...@@ -50,8 +50,6 @@ zig_keywords = {...@@ -50,8 +50,6 @@ zig_keywords = {
50 'anyframe',50 'anyframe',
51 'anytype',51 'anytype',
52 'asm',52 'asm',
53 'async',
54 'await',
55 'break',53 'break',
56 'callconv',54 'callconv',
57 'catch',55 'catch',