mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #24362 (remove async, await, usingnamespace)
remove `async` and `await` keywords; remove `usingnamespace`
This commit is contained in:
commit
fc2c1883b3
@ -460,8 +460,8 @@ pub fn build(b: *std.Build) !void {
|
||||
.skip_linux = skip_linux,
|
||||
.skip_llvm = skip_llvm,
|
||||
.skip_libc = skip_libc,
|
||||
// 2923515904 was observed on an x86_64-linux-gnu host.
|
||||
.max_rss = 3100000000,
|
||||
// 3888779264 was observed on an x86_64-linux-gnu host.
|
||||
.max_rss = 4000000000,
|
||||
}));
|
||||
|
||||
test_modules_step.dependOn(tests.addModuleTests(b, .{
|
||||
|
||||
@ -3842,37 +3842,6 @@ void do_a_thing(struct Foo *foo) {
|
||||
{#header_close#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|usingnamespace#}
|
||||
<p>
|
||||
{#syntax#}usingnamespace{#endsyntax#} is a declaration that mixes all the public
|
||||
declarations of the operand, which must be a {#link|struct#}, {#link|union#}, {#link|enum#},
|
||||
or {#link|opaque#}, into the namespace:
|
||||
</p>
|
||||
{#code|test_usingnamespace.zig#}
|
||||
|
||||
<p>
|
||||
{#syntax#}usingnamespace{#endsyntax#} has an important use case when organizing the public
|
||||
API of a file or package. For example, one might have <code class="file">c.zig</code> with all of the
|
||||
{#link|C imports|Import from C Header File#}:
|
||||
</p>
|
||||
{#syntax_block|zig|c.zig#}
|
||||
pub usingnamespace @cImport({
|
||||
@cInclude("epoxy/gl.h");
|
||||
@cInclude("GLFW/glfw3.h");
|
||||
@cDefine("STBI_ONLY_PNG", "");
|
||||
@cDefine("STBI_NO_STDIO", "");
|
||||
@cInclude("stb_image.h");
|
||||
});
|
||||
{#end_syntax_block#}
|
||||
<p>
|
||||
The above example demonstrates using {#syntax#}pub{#endsyntax#} to qualify the
|
||||
{#syntax#}usingnamespace{#endsyntax#} additionally makes the imported declarations
|
||||
{#syntax#}pub{#endsyntax#}. This can be used to forward declarations, giving precise control
|
||||
over what declarations a given file exposes.
|
||||
</p>
|
||||
{#header_close#}
|
||||
|
||||
|
||||
{#header_open|comptime#}
|
||||
<p>
|
||||
Zig places importance on the concept of whether an expression is known at compile-time.
|
||||
@ -4279,16 +4248,9 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|Async Functions#}
|
||||
<p>Async functions regressed with the release of 0.11.0. Their future in
|
||||
the Zig language is unclear due to multiple unsolved problems:</p>
|
||||
<ul>
|
||||
<li>LLVM's lack of ability to optimize them.</li>
|
||||
<li>Third-party debuggers' lack of ability to debug them.</li>
|
||||
<li><a href="https://github.com/ziglang/zig/issues/5913">The cancellation problem</a>.</li>
|
||||
<li>Async function pointers preventing the stack size from being known.</li>
|
||||
</ul>
|
||||
<p>These problems are surmountable, but it will take time. The Zig team
|
||||
is currently focused on other priorities.</p>
|
||||
<p>Async functions regressed with the release of 0.11.0. The current plan is to
|
||||
reintroduce them as a lower level primitive that powers I/O implementations.</p>
|
||||
<p>Tracking issue: <a href="https://github.com/ziglang/zig/issues/23446">Proposal: stackless coroutines as low-level primitives</a></p>
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|Builtin Functions|2col#}
|
||||
@ -6552,7 +6514,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
|
||||
</p>
|
||||
<ul>
|
||||
<li>If a call to {#syntax#}@import{#endsyntax#} is analyzed, the file being imported is analyzed.</li>
|
||||
<li>If a type (including a file) is analyzed, all {#syntax#}comptime{#endsyntax#}, {#syntax#}usingnamespace{#endsyntax#}, and {#syntax#}export{#endsyntax#} declarations within it are analyzed.</li>
|
||||
<li>If a type (including a file) is analyzed, all {#syntax#}comptime{#endsyntax#} and {#syntax#}export{#endsyntax#} declarations within it are analyzed.</li>
|
||||
<li>If a type (including a file) is analyzed, and the compilation is for a {#link|test|Zig Test#}, and the module the type is within is the root module of the compilation, then all {#syntax#}test{#endsyntax#} declarations within it are also analyzed.</li>
|
||||
<li>If a reference to a named declaration (i.e. a usage of it) is analyzed, the declaration being referenced is analyzed. Declarations are order-independent, so this reference may be above or below the declaration being referenced, or even in another file entirely.</li>
|
||||
</ul>
|
||||
@ -7372,29 +7334,6 @@ fn readU32Be() u32 {}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<pre>{#syntax#}async{#endsyntax#}</pre>
|
||||
</th>
|
||||
<td>
|
||||
{#syntax#}async{#endsyntax#} can be used before a function call to get a pointer to the function's frame when it suspends.
|
||||
<ul>
|
||||
<li>See also {#link|Async Functions#}</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<pre>{#syntax#}await{#endsyntax#}</pre>
|
||||
</th>
|
||||
<td>
|
||||
{#syntax#}await{#endsyntax#} can be used to suspend the current function until the frame provided after the {#syntax#}await{#endsyntax#} completes.
|
||||
{#syntax#}await{#endsyntax#} copies the value returned from the target function's frame to the caller.
|
||||
<ul>
|
||||
<li>See also {#link|Async Functions#}</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<pre>{#syntax#}break{#endsyntax#}</pre>
|
||||
@ -7812,18 +7751,6 @@ fn readU32Be() u32 {}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<pre>{#syntax#}usingnamespace{#endsyntax#}</pre>
|
||||
</th>
|
||||
<td>
|
||||
{#syntax#}usingnamespace{#endsyntax#} is a top-level declaration that imports all the public declarations of the operand,
|
||||
which must be a struct, union, or enum, into the current scope.
|
||||
<ul>
|
||||
<li>See also {#link|usingnamespace#}</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<pre>{#syntax#}var{#endsyntax#}</pre>
|
||||
@ -7893,7 +7820,6 @@ ComptimeDecl <- KEYWORD_comptime Block
|
||||
Decl
|
||||
<- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block)
|
||||
/ (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? GlobalVarDecl
|
||||
/ KEYWORD_usingnamespace Expr SEMICOLON
|
||||
|
||||
FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
|
||||
|
||||
@ -8006,8 +7932,7 @@ TypeExpr <- PrefixTypeOp* ErrorUnionExpr
|
||||
ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
|
||||
|
||||
SuffixExpr
|
||||
<- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
|
||||
/ PrimaryTypeExpr (SuffixOp / FnCallArguments)*
|
||||
<- PrimaryTypeExpr (SuffixOp / FnCallArguments)*
|
||||
|
||||
PrimaryTypeExpr
|
||||
<- BUILTINIDENTIFIER FnCallArguments
|
||||
@ -8183,7 +8108,6 @@ PrefixOp
|
||||
/ MINUSPERCENT
|
||||
/ AMPERSAND
|
||||
/ KEYWORD_try
|
||||
/ KEYWORD_await
|
||||
|
||||
PrefixTypeOp
|
||||
<- QUESTIONMARK
|
||||
@ -8404,8 +8328,6 @@ KEYWORD_and <- 'and' end_of_word
|
||||
KEYWORD_anyframe <- 'anyframe' end_of_word
|
||||
KEYWORD_anytype <- 'anytype' end_of_word
|
||||
KEYWORD_asm <- 'asm' end_of_word
|
||||
KEYWORD_async <- 'async' end_of_word
|
||||
KEYWORD_await <- 'await' end_of_word
|
||||
KEYWORD_break <- 'break' end_of_word
|
||||
KEYWORD_callconv <- 'callconv' end_of_word
|
||||
KEYWORD_catch <- 'catch' end_of_word
|
||||
@ -8442,14 +8364,13 @@ KEYWORD_threadlocal <- 'threadlocal' end_of_word
|
||||
KEYWORD_try <- 'try' end_of_word
|
||||
KEYWORD_union <- 'union' end_of_word
|
||||
KEYWORD_unreachable <- 'unreachable' end_of_word
|
||||
KEYWORD_usingnamespace <- 'usingnamespace' end_of_word
|
||||
KEYWORD_var <- 'var' end_of_word
|
||||
KEYWORD_volatile <- 'volatile' end_of_word
|
||||
KEYWORD_while <- 'while' end_of_word
|
||||
|
||||
keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and
|
||||
/ KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm / KEYWORD_async
|
||||
/ KEYWORD_await / KEYWORD_break / KEYWORD_callconv / KEYWORD_catch
|
||||
/ KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_asm
|
||||
/ KEYWORD_break / KEYWORD_callconv / KEYWORD_catch
|
||||
/ KEYWORD_comptime / KEYWORD_const / KEYWORD_continue / KEYWORD_defer
|
||||
/ KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export
|
||||
/ KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if
|
||||
@ -8458,7 +8379,7 @@ keyword <- KEYWORD_addrspace / KEYWORD_align / KEYWORD_allowzero / KEYWORD_and
|
||||
/ KEYWORD_pub / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
|
||||
/ KEYWORD_struct / KEYWORD_suspend / KEYWORD_switch / KEYWORD_test
|
||||
/ KEYWORD_threadlocal / KEYWORD_try / KEYWORD_union / KEYWORD_unreachable
|
||||
/ KEYWORD_usingnamespace / KEYWORD_var / KEYWORD_volatile / KEYWORD_while
|
||||
/ KEYWORD_var / KEYWORD_volatile / KEYWORD_while
|
||||
{#end_syntax_block#}
|
||||
{#header_close#}
|
||||
{#header_open|Zen#}
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
test "using std namespace" {
|
||||
const S = struct {
|
||||
usingnamespace @import("std");
|
||||
};
|
||||
try S.testing.expect(true);
|
||||
}
|
||||
|
||||
// test
|
||||
@ -160,12 +160,6 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
|
||||
try walkExpression(w, decl);
|
||||
},
|
||||
|
||||
.@"usingnamespace" => {
|
||||
try w.transformations.append(.{ .delete_node = decl });
|
||||
const expr = ast.nodeData(decl).node;
|
||||
try walkExpression(w, expr);
|
||||
},
|
||||
|
||||
.global_var_decl,
|
||||
.local_var_decl,
|
||||
.simple_var_decl,
|
||||
@ -335,7 +329,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
|
||||
.address_of,
|
||||
.@"try",
|
||||
.@"resume",
|
||||
.@"await",
|
||||
.deref,
|
||||
=> {
|
||||
return walkExpression(w, ast.nodeData(node).node);
|
||||
@ -379,12 +372,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
|
||||
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
return walkCall(w, ast.fullCall(&buf, node).?);
|
||||
@ -525,7 +514,6 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
|
||||
.local_var_decl => unreachable,
|
||||
.simple_var_decl => unreachable,
|
||||
.aligned_var_decl => unreachable,
|
||||
.@"usingnamespace" => unreachable,
|
||||
.test_decl => unreachable,
|
||||
.asm_output => unreachable,
|
||||
.asm_input => unreachable,
|
||||
|
||||
@ -238,12 +238,8 @@ pub const File = struct {
|
||||
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
return categorize_call(file_index, node, ast.fullCall(&buf, node).?);
|
||||
@ -571,7 +567,6 @@ fn struct_decl(
|
||||
},
|
||||
|
||||
.@"comptime",
|
||||
.@"usingnamespace",
|
||||
=> try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node),
|
||||
|
||||
.test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]),
|
||||
@ -643,7 +638,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
const ast = w.file.get_ast();
|
||||
switch (ast.nodeTag(node)) {
|
||||
.root => unreachable, // Top-level declaration.
|
||||
.@"usingnamespace" => unreachable, // Top-level declaration.
|
||||
.test_decl => unreachable, // Top-level declaration.
|
||||
.container_field_init => unreachable, // Top-level declaration.
|
||||
.container_field_align => unreachable, // Top-level declaration.
|
||||
@ -743,7 +737,6 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
.@"comptime",
|
||||
.@"nosuspend",
|
||||
.@"suspend",
|
||||
.@"await",
|
||||
.@"resume",
|
||||
.@"try",
|
||||
=> try expr(w, scope, parent_decl, ast.nodeData(node).node),
|
||||
@ -806,12 +799,8 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
|
||||
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
const full = ast.fullCall(&buf, node).?;
|
||||
|
||||
@ -101,8 +101,6 @@ pub fn fileSourceHtml(
|
||||
.keyword_align,
|
||||
.keyword_and,
|
||||
.keyword_asm,
|
||||
.keyword_async,
|
||||
.keyword_await,
|
||||
.keyword_break,
|
||||
.keyword_catch,
|
||||
.keyword_comptime,
|
||||
@ -139,7 +137,6 @@ pub fn fileSourceHtml(
|
||||
.keyword_try,
|
||||
.keyword_union,
|
||||
.keyword_unreachable,
|
||||
.keyword_usingnamespace,
|
||||
.keyword_var,
|
||||
.keyword_volatile,
|
||||
.keyword_allowzero,
|
||||
|
||||
@ -572,7 +572,7 @@ pub fn appendZigProcessFlags(
|
||||
try zig_args.append(switch (unwind_tables) {
|
||||
.none => "-fno-unwind-tables",
|
||||
.sync => "-funwind-tables",
|
||||
.@"async" => "-fasync-unwind-tables",
|
||||
.async => "-fasync-unwind-tables",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1691,7 +1691,7 @@ pub const Cpu = struct {
|
||||
pub fn fromCallingConvention(cc: std.builtin.CallingConvention.Tag) []const Arch {
|
||||
return switch (cc) {
|
||||
.auto,
|
||||
.@"async",
|
||||
.async,
|
||||
.naked,
|
||||
.@"inline",
|
||||
=> unreachable,
|
||||
|
||||
@ -199,8 +199,6 @@ pub const CallingConvention = union(enum(u8)) {
|
||||
pub const C: CallingConvention = .c;
|
||||
/// Deprecated; use `.naked`.
|
||||
pub const Naked: CallingConvention = .naked;
|
||||
/// Deprecated; use `.@"async"`.
|
||||
pub const Async: CallingConvention = .@"async";
|
||||
/// Deprecated; use `.@"inline"`.
|
||||
pub const Inline: CallingConvention = .@"inline";
|
||||
/// Deprecated; use `.x86_64_interrupt`, `.x86_interrupt`, or `.avr_interrupt`.
|
||||
@ -248,7 +246,7 @@ pub const CallingConvention = union(enum(u8)) {
|
||||
/// The calling convention of a function that can be called with `async` syntax. An `async` call
|
||||
/// of a runtime-known function must target a function with this calling convention.
|
||||
/// Comptime-known functions with other calling conventions may be coerced to this one.
|
||||
@"async",
|
||||
async,
|
||||
|
||||
/// Functions with this calling convention have no prologue or epilogue, making the function
|
||||
/// uncallable in regular Zig code. This can be useful when integrating with assembly.
|
||||
@ -851,7 +849,7 @@ pub const LinkMode = enum {
|
||||
pub const UnwindTables = enum {
|
||||
none,
|
||||
sync,
|
||||
@"async",
|
||||
async,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
@ -866,32 +864,23 @@ pub const WasiExecModel = enum {
|
||||
pub const CallModifier = enum {
|
||||
/// Equivalent to function call syntax.
|
||||
auto,
|
||||
|
||||
/// Equivalent to async keyword used with function call syntax.
|
||||
async_kw,
|
||||
|
||||
/// Prevents tail call optimization. This guarantees that the return
|
||||
/// address will point to the callsite, as opposed to the callsite's
|
||||
/// callsite. If the call is otherwise required to be tail-called
|
||||
/// or inlined, a compile error is emitted instead.
|
||||
never_tail,
|
||||
|
||||
/// Guarantees that the call will not be inlined. If the call is
|
||||
/// otherwise required to be inlined, a compile error is emitted instead.
|
||||
never_inline,
|
||||
|
||||
/// Asserts that the function call will not suspend. This allows a
|
||||
/// non-async function to call an async function.
|
||||
no_async,
|
||||
|
||||
no_suspend,
|
||||
/// Guarantees that the call will be generated with tail call optimization.
|
||||
/// If this is not possible, a compile error is emitted instead.
|
||||
always_tail,
|
||||
|
||||
/// Guarantees that the call will be inlined at the callsite.
|
||||
/// If this is not possible, a compile error is emitted instead.
|
||||
always_inline,
|
||||
|
||||
/// Evaluates the call at compile-time. If the call cannot be completed at
|
||||
/// compile-time, a compile error is emitted instead.
|
||||
compile_time,
|
||||
|
||||
@ -606,7 +606,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
|
||||
.negation_wrap,
|
||||
.address_of,
|
||||
.@"try",
|
||||
.@"await",
|
||||
.optional_type,
|
||||
.@"switch",
|
||||
.switch_comma,
|
||||
@ -756,27 +755,6 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
|
||||
return i - end_offset;
|
||||
},
|
||||
|
||||
.@"usingnamespace" => {
|
||||
const main_token: TokenIndex = tree.nodeMainToken(n);
|
||||
const has_visib_token = tree.isTokenPrecededByTags(main_token, &.{.keyword_pub});
|
||||
end_offset += @intFromBool(has_visib_token);
|
||||
return main_token - end_offset;
|
||||
},
|
||||
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
=> {
|
||||
end_offset += 1; // async token
|
||||
n = tree.nodeData(n).node_and_opt_node[0];
|
||||
},
|
||||
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> {
|
||||
end_offset += 1; // async token
|
||||
n = tree.nodeData(n).node_and_extra[0];
|
||||
},
|
||||
|
||||
.container_field_init,
|
||||
.container_field_align,
|
||||
.container_field,
|
||||
@ -896,14 +874,12 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
|
||||
while (true) switch (tree.nodeTag(n)) {
|
||||
.root => return @intCast(tree.tokens.len - 1),
|
||||
|
||||
.@"usingnamespace",
|
||||
.bool_not,
|
||||
.negation,
|
||||
.bit_not,
|
||||
.negation_wrap,
|
||||
.address_of,
|
||||
.@"try",
|
||||
.@"await",
|
||||
.optional_type,
|
||||
.@"suspend",
|
||||
.@"resume",
|
||||
@ -1022,7 +998,7 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
|
||||
};
|
||||
},
|
||||
|
||||
.call, .async_call => {
|
||||
.call => {
|
||||
_, const extra_index = tree.nodeData(n).node_and_extra;
|
||||
const params = tree.extraData(extra_index, Node.SubRange);
|
||||
assert(params.start != params.end);
|
||||
@ -1041,7 +1017,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
|
||||
}
|
||||
},
|
||||
.call_comma,
|
||||
.async_call_comma,
|
||||
.tagged_union_enum_tag_trailing,
|
||||
=> {
|
||||
_, const extra_index = tree.nodeData(n).node_and_extra;
|
||||
@ -1122,7 +1097,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
|
||||
n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member
|
||||
},
|
||||
.call_one,
|
||||
.async_call_one,
|
||||
=> {
|
||||
_, const first_param = tree.nodeData(n).node_and_opt_node;
|
||||
end_offset += 1; // for the rparen
|
||||
@ -1271,7 +1245,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
|
||||
n = first_element;
|
||||
},
|
||||
.call_one_comma,
|
||||
.async_call_one_comma,
|
||||
.struct_init_one_comma,
|
||||
=> {
|
||||
_, const first_field = tree.nodeData(n).node_and_opt_node;
|
||||
@ -1988,21 +1961,21 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {
|
||||
pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {
|
||||
const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;
|
||||
const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
|
||||
return tree.fullCallComponents(.{
|
||||
return .{ .ast = .{
|
||||
.lparen = tree.nodeMainToken(node),
|
||||
.fn_expr = fn_expr,
|
||||
.params = params,
|
||||
});
|
||||
} };
|
||||
}
|
||||
|
||||
pub fn callFull(tree: Ast, node: Node.Index) full.Call {
|
||||
const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;
|
||||
const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
|
||||
return tree.fullCallComponents(.{
|
||||
return .{ .ast = .{
|
||||
.lparen = tree.nodeMainToken(node),
|
||||
.fn_expr = fn_expr,
|
||||
.params = params,
|
||||
});
|
||||
} };
|
||||
}
|
||||
|
||||
fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {
|
||||
@ -2336,18 +2309,6 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
|
||||
return result;
|
||||
}
|
||||
|
||||
fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {
|
||||
var result: full.Call = .{
|
||||
.ast = info,
|
||||
.async_token = null,
|
||||
};
|
||||
const first_token = tree.firstToken(info.fn_expr);
|
||||
if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) {
|
||||
result.async_token = first_token - 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
|
||||
return switch (tree.nodeTag(node)) {
|
||||
.global_var_decl => tree.globalVarDecl(node),
|
||||
@ -2488,8 +2449,8 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
|
||||
|
||||
pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {
|
||||
return switch (tree.nodeTag(node)) {
|
||||
.call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
|
||||
.call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),
|
||||
.call, .call_comma => tree.callFull(node),
|
||||
.call_one, .call_one_comma => tree.callOne(buffer, node),
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
@ -2882,7 +2843,6 @@ pub const full = struct {
|
||||
|
||||
pub const Call = struct {
|
||||
ast: Components,
|
||||
async_token: ?TokenIndex,
|
||||
|
||||
pub const Components = struct {
|
||||
lparen: TokenIndex,
|
||||
@ -3065,12 +3025,6 @@ pub const Node = struct {
|
||||
///
|
||||
/// The `main_token` field is the first token for the source file.
|
||||
root,
|
||||
/// `usingnamespace expr;`.
|
||||
///
|
||||
/// The `data` field is a `.node` to expr.
|
||||
///
|
||||
/// The `main_token` field is the `usingnamespace` token.
|
||||
@"usingnamespace",
|
||||
/// `test {}`,
|
||||
/// `test "name" {}`,
|
||||
/// `test identifier {}`.
|
||||
@ -3301,8 +3255,6 @@ pub const Node = struct {
|
||||
address_of,
|
||||
/// `try expr`. The `main_token` field is the `try` token.
|
||||
@"try",
|
||||
/// `await expr`. The `main_token` field is the `await` token.
|
||||
@"await",
|
||||
/// `?expr`. The `main_token` field is the `?` token.
|
||||
optional_type,
|
||||
/// `[lhs]rhs`. The `main_token` field is the `[` token.
|
||||
@ -3498,17 +3450,6 @@ pub const Node = struct {
|
||||
/// Same as `call_one` except there is known to be a trailing comma
|
||||
/// before the final rparen.
|
||||
call_one_comma,
|
||||
/// `async a(b)`, `async a()`.
|
||||
///
|
||||
/// The `data` field is a `.node_and_opt_node`:
|
||||
/// 1. a `Node.Index` to the function expression.
|
||||
/// 2. a `Node.OptionalIndex` to the first argument, if any.
|
||||
///
|
||||
/// The `main_token` field is the `(` token.
|
||||
async_call_one,
|
||||
/// Same as `async_call_one` except there is known to be a trailing
|
||||
/// comma before the final rparen.
|
||||
async_call_one_comma,
|
||||
/// `a(b, c, d)`.
|
||||
///
|
||||
/// The `data` field is a `.node_and_extra`:
|
||||
@ -3521,18 +3462,6 @@ pub const Node = struct {
|
||||
/// Same as `call` except there is known to be a trailing comma before
|
||||
/// the final rparen.
|
||||
call_comma,
|
||||
/// `async a(b, c, d)`.
|
||||
///
|
||||
/// The `data` field is a `.node_and_extra`:
|
||||
/// 1. a `Node.Index` to the function expression.
|
||||
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
|
||||
/// each argument.
|
||||
///
|
||||
/// The `main_token` field is the `(` token.
|
||||
async_call,
|
||||
/// Same as `async_call` except there is known to be a trailing comma
|
||||
/// before the final rparen.
|
||||
async_call_comma,
|
||||
/// `switch(a) {}`.
|
||||
///
|
||||
/// The `data` field is a `.node_and_extra`:
|
||||
|
||||
@ -442,7 +442,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
|
||||
const tree = astgen.tree;
|
||||
switch (tree.nodeTag(node)) {
|
||||
.root => unreachable,
|
||||
.@"usingnamespace" => unreachable,
|
||||
.test_decl => unreachable,
|
||||
.global_var_decl => unreachable,
|
||||
.local_var_decl => unreachable,
|
||||
@ -510,12 +509,8 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
|
||||
.number_literal,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.unreachable_literal,
|
||||
.@"return",
|
||||
.@"if",
|
||||
@ -547,7 +542,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
|
||||
.merge_error_sets,
|
||||
.switch_range,
|
||||
.for_range,
|
||||
.@"await",
|
||||
.bit_not,
|
||||
.negation,
|
||||
.negation_wrap,
|
||||
@ -642,7 +636,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
|
||||
|
||||
switch (tree.nodeTag(node)) {
|
||||
.root => unreachable, // Top-level declaration.
|
||||
.@"usingnamespace" => unreachable, // Top-level declaration.
|
||||
.test_decl => unreachable, // Top-level declaration.
|
||||
.container_field_init => unreachable, // Top-level declaration.
|
||||
.container_field_align => unreachable, // Top-level declaration.
|
||||
@ -836,12 +829,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
|
||||
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
return callExpr(gz, scope, ri, .none, node, tree.fullCall(&buf, node).?);
|
||||
@ -1114,7 +1103,6 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
|
||||
|
||||
.@"nosuspend" => return nosuspendExpr(gz, scope, ri, node),
|
||||
.@"suspend" => return suspendExpr(gz, scope, node),
|
||||
.@"await" => return awaitExpr(gz, scope, ri, node),
|
||||
.@"resume" => return resumeExpr(gz, scope, ri, node),
|
||||
|
||||
.@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),
|
||||
@ -1259,33 +1247,6 @@ fn suspendExpr(
|
||||
return suspend_inst.toRef();
|
||||
}
|
||||
|
||||
fn awaitExpr(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
ri: ResultInfo,
|
||||
node: Ast.Node.Index,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const tree = astgen.tree;
|
||||
const rhs_node = tree.nodeData(node).node;
|
||||
|
||||
if (gz.suspend_node.unwrap()) |suspend_node| {
|
||||
return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
|
||||
try astgen.errNoteNode(suspend_node, "suspend block here", .{}),
|
||||
});
|
||||
}
|
||||
const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
|
||||
const result = if (gz.nosuspend_node != .none)
|
||||
try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = operand,
|
||||
})
|
||||
else
|
||||
try gz.addUnNode(.@"await", operand, node);
|
||||
|
||||
return rvalue(gz, ri, result, node);
|
||||
}
|
||||
|
||||
fn resumeExpr(
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
@ -2853,7 +2814,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
||||
.tag_name,
|
||||
.type_name,
|
||||
.frame_type,
|
||||
.frame_size,
|
||||
.int_from_float,
|
||||
.float_from_int,
|
||||
.ptr_from_int,
|
||||
@ -2887,7 +2847,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
||||
.min,
|
||||
.c_import,
|
||||
.@"resume",
|
||||
.@"await",
|
||||
.ret_err_value_code,
|
||||
.ret_ptr,
|
||||
.ret_type,
|
||||
@ -4739,69 +4698,6 @@ fn comptimeDecl(
|
||||
});
|
||||
}
|
||||
|
||||
fn usingnamespaceDecl(
|
||||
astgen: *AstGen,
|
||||
gz: *GenZir,
|
||||
scope: *Scope,
|
||||
wip_members: *WipMembers,
|
||||
node: Ast.Node.Index,
|
||||
) InnerError!void {
|
||||
const tree = astgen.tree;
|
||||
|
||||
const old_hasher = astgen.src_hasher;
|
||||
defer astgen.src_hasher = old_hasher;
|
||||
astgen.src_hasher = std.zig.SrcHasher.init(.{});
|
||||
astgen.src_hasher.update(tree.getNodeSource(node));
|
||||
astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
|
||||
|
||||
const type_expr = tree.nodeData(node).node;
|
||||
const is_pub = tree.isTokenPrecededByTags(tree.nodeMainToken(node), &.{.keyword_pub});
|
||||
|
||||
// Up top so the ZIR instruction index marks the start range of this
|
||||
// top-level declaration.
|
||||
const decl_inst = try gz.makeDeclaration(node);
|
||||
wip_members.nextDecl(decl_inst);
|
||||
astgen.advanceSourceCursorToNode(node);
|
||||
|
||||
// This is just needed for the `setDeclaration` call.
|
||||
var dummy_gz = gz.makeSubBlock(scope);
|
||||
defer dummy_gz.unstack();
|
||||
|
||||
var usingnamespace_gz: GenZir = .{
|
||||
.is_comptime = true,
|
||||
.decl_node_index = node,
|
||||
.decl_line = astgen.source_line,
|
||||
.parent = scope,
|
||||
.astgen = astgen,
|
||||
.instructions = gz.instructions,
|
||||
.instructions_top = gz.instructions.items.len,
|
||||
};
|
||||
defer usingnamespace_gz.unstack();
|
||||
|
||||
const decl_column = astgen.source_column;
|
||||
|
||||
const namespace_inst = try typeExpr(&usingnamespace_gz, &usingnamespace_gz.base, type_expr);
|
||||
_ = try usingnamespace_gz.addBreak(.break_inline, decl_inst, namespace_inst);
|
||||
|
||||
var hash: std.zig.SrcHash = undefined;
|
||||
astgen.src_hasher.final(&hash);
|
||||
try setDeclaration(decl_inst, .{
|
||||
.src_hash = hash,
|
||||
.src_line = usingnamespace_gz.decl_line,
|
||||
.src_column = decl_column,
|
||||
.kind = .@"usingnamespace",
|
||||
.name = .empty,
|
||||
.is_pub = is_pub,
|
||||
.is_threadlocal = false,
|
||||
.linkage = .normal,
|
||||
.type_gz = &dummy_gz,
|
||||
.align_gz = &dummy_gz,
|
||||
.linksection_gz = &dummy_gz,
|
||||
.addrspace_gz = &dummy_gz,
|
||||
.value_gz = &usingnamespace_gz,
|
||||
});
|
||||
}
|
||||
|
||||
fn testDecl(
|
||||
astgen: *AstGen,
|
||||
gz: *GenZir,
|
||||
@ -5971,23 +5867,6 @@ fn containerMember(
|
||||
},
|
||||
};
|
||||
},
|
||||
.@"usingnamespace" => {
|
||||
const prev_decl_index = wip_members.decl_index;
|
||||
astgen.usingnamespaceDecl(gz, scope, wip_members, member_node) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {
|
||||
wip_members.decl_index = prev_decl_index;
|
||||
try addFailedDeclaration(
|
||||
wip_members,
|
||||
gz,
|
||||
.@"usingnamespace",
|
||||
.empty,
|
||||
member_node,
|
||||
tree.isTokenPrecededByTags(tree.nodeMainToken(member_node), &.{.keyword_pub}),
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
.test_decl => {
|
||||
const prev_decl_index = wip_members.decl_index;
|
||||
// We need to have *some* decl here so that the decl count matches what's expected.
|
||||
@ -9501,7 +9380,6 @@ fn builtinCall(
|
||||
.tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name),
|
||||
.type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name),
|
||||
.Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type),
|
||||
.frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size),
|
||||
|
||||
.int_from_float => return typeCast(gz, scope, ri, node, params[0], .int_from_float, builtin_name),
|
||||
.float_from_int => return typeCast(gz, scope, ri, node, params[0], .float_from_int, builtin_name),
|
||||
@ -9767,16 +9645,6 @@ fn builtinCall(
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.async_call => {
|
||||
const result = try gz.addExtendedPayload(.builtin_async_call, Zir.Inst.AsyncCall{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.frame_buffer = try expr(gz, scope, .{ .rl = .none }, params[0]),
|
||||
.result_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]),
|
||||
.fn_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]),
|
||||
.args = try expr(gz, scope, .{ .rl = .none }, params[3]),
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.Vector => {
|
||||
const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
|
||||
.lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .type),
|
||||
@ -10175,11 +10043,8 @@ fn callExpr(
|
||||
|
||||
const callee = try calleeExpr(gz, scope, ri.rl, override_decl_literal_type, call.ast.fn_expr);
|
||||
const modifier: std.builtin.CallModifier = blk: {
|
||||
if (call.async_token != null) {
|
||||
break :blk .async_kw;
|
||||
}
|
||||
if (gz.nosuspend_node != .none) {
|
||||
break :blk .no_async;
|
||||
break :blk .no_suspend;
|
||||
}
|
||||
break :blk .auto;
|
||||
};
|
||||
@ -10451,7 +10316,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
|
||||
while (true) {
|
||||
switch (tree.nodeTag(node)) {
|
||||
.root,
|
||||
.@"usingnamespace",
|
||||
.test_decl,
|
||||
.switch_case,
|
||||
.switch_case_inline,
|
||||
@ -10483,12 +10347,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
|
||||
.switch_comma,
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> return .maybe,
|
||||
|
||||
.@"return",
|
||||
@ -10613,7 +10473,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
|
||||
|
||||
// Forward the question to the LHS sub-expression.
|
||||
.@"try",
|
||||
.@"await",
|
||||
.@"comptime",
|
||||
.@"nosuspend",
|
||||
=> node = tree.nodeData(node).node,
|
||||
@ -10664,7 +10523,6 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
|
||||
while (true) {
|
||||
switch (tree.nodeTag(node)) {
|
||||
.root,
|
||||
.@"usingnamespace",
|
||||
.test_decl,
|
||||
.switch_case,
|
||||
.switch_case_inline,
|
||||
@ -10803,12 +10661,8 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
|
||||
.switch_comma,
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
.block_two,
|
||||
.block_two_semicolon,
|
||||
.block,
|
||||
@ -10826,7 +10680,6 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
|
||||
|
||||
// Forward the question to the LHS sub-expression.
|
||||
.@"try",
|
||||
.@"await",
|
||||
.@"comptime",
|
||||
.@"nosuspend",
|
||||
=> node = tree.nodeData(node).node,
|
||||
@ -10908,7 +10761,6 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
|
||||
while (true) {
|
||||
switch (tree.nodeTag(node)) {
|
||||
.root,
|
||||
.@"usingnamespace",
|
||||
.test_decl,
|
||||
.switch_case,
|
||||
.switch_case_inline,
|
||||
@ -11047,12 +10899,8 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
|
||||
.switch_comma,
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
.block_two,
|
||||
.block_two_semicolon,
|
||||
.block,
|
||||
@ -11079,7 +10927,6 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
|
||||
|
||||
// Forward the question to the LHS sub-expression.
|
||||
.@"try",
|
||||
.@"await",
|
||||
.@"comptime",
|
||||
.@"nosuspend",
|
||||
=> node = tree.nodeData(node).node,
|
||||
@ -13586,7 +13433,7 @@ fn scanContainer(
|
||||
break :blk .{ .decl, ident };
|
||||
},
|
||||
|
||||
.@"comptime", .@"usingnamespace" => {
|
||||
.@"comptime" => {
|
||||
decl_count += 1;
|
||||
continue;
|
||||
},
|
||||
@ -13964,7 +13811,6 @@ const DeclarationName = union(enum) {
|
||||
decltest: Ast.TokenIndex,
|
||||
unnamed_test,
|
||||
@"comptime",
|
||||
@"usingnamespace",
|
||||
};
|
||||
|
||||
fn addFailedDeclaration(
|
||||
@ -14054,7 +13900,6 @@ fn setDeclaration(
|
||||
.@"test" => .@"test",
|
||||
.decltest => .decltest,
|
||||
.@"comptime" => .@"comptime",
|
||||
.@"usingnamespace" => if (args.is_pub) .pub_usingnamespace else .@"usingnamespace",
|
||||
.@"const" => switch (args.linkage) {
|
||||
.normal => if (args.is_pub) id: {
|
||||
if (has_special_body) break :id .pub_const;
|
||||
|
||||
@ -165,10 +165,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
|
||||
}
|
||||
return false;
|
||||
},
|
||||
.@"usingnamespace" => {
|
||||
_ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only);
|
||||
return false;
|
||||
},
|
||||
.test_decl => {
|
||||
_ = try astrl.expr(tree.nodeData(node).opt_token_and_node[1], block, ResultInfo.none);
|
||||
return false;
|
||||
@ -334,12 +330,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
|
||||
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
const full = tree.fullCall(&buf, node).?;
|
||||
@ -353,11 +345,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
|
||||
.call,
|
||||
.call_comma,
|
||||
=> false, // TODO: once function calls are passed result locations this will change
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> ri.have_ptr, // always use result ptr for frames
|
||||
else => unreachable,
|
||||
};
|
||||
},
|
||||
@ -503,7 +490,6 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
|
||||
return false;
|
||||
},
|
||||
.@"try",
|
||||
.@"await",
|
||||
.@"nosuspend",
|
||||
=> return astrl.expr(tree.nodeData(node).node, block, ri),
|
||||
.grouped_expression,
|
||||
@ -948,7 +934,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
|
||||
.tag_name,
|
||||
.type_name,
|
||||
.Frame,
|
||||
.frame_size,
|
||||
.int_from_float,
|
||||
.float_from_int,
|
||||
.ptr_from_int,
|
||||
@ -1079,13 +1064,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
|
||||
_ = try astrl.expr(args[3], block, ResultInfo.none);
|
||||
return false;
|
||||
},
|
||||
.async_call => {
|
||||
_ = try astrl.expr(args[0], block, ResultInfo.none);
|
||||
_ = try astrl.expr(args[1], block, ResultInfo.none);
|
||||
_ = try astrl.expr(args[2], block, ResultInfo.none);
|
||||
_ = try astrl.expr(args[3], block, ResultInfo.none);
|
||||
return false; // buffer passed as arg for frame data
|
||||
},
|
||||
.Vector => {
|
||||
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
|
||||
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
|
||||
|
||||
@ -4,7 +4,6 @@ pub const Tag = enum {
|
||||
align_cast,
|
||||
align_of,
|
||||
as,
|
||||
async_call,
|
||||
atomic_load,
|
||||
atomic_rmw,
|
||||
atomic_store,
|
||||
@ -55,7 +54,6 @@ pub const Tag = enum {
|
||||
frame,
|
||||
Frame,
|
||||
frame_address,
|
||||
frame_size,
|
||||
has_decl,
|
||||
has_field,
|
||||
import,
|
||||
@ -184,13 +182,6 @@ pub const list = list: {
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@asyncCall",
|
||||
.{
|
||||
.tag = .async_call,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@atomicLoad",
|
||||
.{
|
||||
@ -550,13 +541,6 @@ pub const list = list: {
|
||||
.illegal_outside_function = true,
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@frameSize",
|
||||
.{
|
||||
.tag = .frame_size,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@hasDecl",
|
||||
.{
|
||||
|
||||
@ -359,16 +359,6 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
|
||||
}
|
||||
trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
|
||||
},
|
||||
.keyword_usingnamespace => {
|
||||
const opt_node = try p.expectUsingNamespaceRecoverable();
|
||||
if (opt_node) |node| {
|
||||
if (field_state == .seen) {
|
||||
field_state = .{ .end = node };
|
||||
}
|
||||
try p.scratch.append(p.gpa, node);
|
||||
}
|
||||
trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
|
||||
},
|
||||
.keyword_const,
|
||||
.keyword_var,
|
||||
.keyword_threadlocal,
|
||||
@ -496,7 +486,6 @@ fn findNextContainerMember(p: *Parse) void {
|
||||
.keyword_extern,
|
||||
.keyword_inline,
|
||||
.keyword_noinline,
|
||||
.keyword_usingnamespace,
|
||||
.keyword_threadlocal,
|
||||
.keyword_const,
|
||||
.keyword_var,
|
||||
@ -601,7 +590,6 @@ fn expectTestDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
|
||||
/// Decl
|
||||
/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block)
|
||||
/// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
|
||||
/// / KEYWORD_usingnamespace Expr SEMICOLON
|
||||
fn expectTopLevelDecl(p: *Parse) !?Node.Index {
|
||||
const extern_export_inline_token = p.nextToken();
|
||||
var is_extern: bool = false;
|
||||
@ -664,11 +652,8 @@ fn expectTopLevelDecl(p: *Parse) !?Node.Index {
|
||||
if (expect_var_or_fn) {
|
||||
return p.fail(.expected_var_decl_or_fn);
|
||||
}
|
||||
if (p.tokenTag(p.tok_i) != .keyword_usingnamespace) {
|
||||
return p.fail(.expected_pub_item);
|
||||
}
|
||||
return try p.expectUsingNamespace();
|
||||
}
|
||||
|
||||
fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
|
||||
return p.expectTopLevelDecl() catch |err| switch (err) {
|
||||
@ -680,27 +665,6 @@ fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
|
||||
};
|
||||
}
|
||||
|
||||
fn expectUsingNamespace(p: *Parse) !Node.Index {
|
||||
const usingnamespace_token = p.assertToken(.keyword_usingnamespace);
|
||||
const expr = try p.expectExpr();
|
||||
try p.expectSemicolon(.expected_semi_after_decl, false);
|
||||
return p.addNode(.{
|
||||
.tag = .@"usingnamespace",
|
||||
.main_token = usingnamespace_token,
|
||||
.data = .{ .node = expr },
|
||||
});
|
||||
}
|
||||
|
||||
fn expectUsingNamespaceRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
|
||||
return p.expectUsingNamespace() catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.ParseError => {
|
||||
p.findNextContainerMember();
|
||||
return null;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
|
||||
fn parseFnProto(p: *Parse) !?Node.Index {
|
||||
const fn_token = p.eatToken(.keyword_fn) orelse return null;
|
||||
@ -1688,7 +1652,6 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index {
|
||||
/// / MINUSPERCENT
|
||||
/// / AMPERSAND
|
||||
/// / KEYWORD_try
|
||||
/// / KEYWORD_await
|
||||
fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
|
||||
const tag: Node.Tag = switch (p.tokenTag(p.tok_i)) {
|
||||
.bang => .bool_not,
|
||||
@ -1697,7 +1660,6 @@ fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
|
||||
.minus_percent => .negation_wrap,
|
||||
.ampersand => .address_of,
|
||||
.keyword_try => .@"try",
|
||||
.keyword_await => .@"await",
|
||||
else => return p.parsePrimaryExpr(),
|
||||
};
|
||||
return try p.addNode(.{
|
||||
@ -2385,62 +2347,12 @@ fn parseErrorUnionExpr(p: *Parse) !?Node.Index {
|
||||
}
|
||||
|
||||
/// SuffixExpr
|
||||
/// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
|
||||
/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
|
||||
/// <- PrimaryTypeExpr (SuffixOp / FnCallArguments)*
|
||||
///
|
||||
/// FnCallArguments <- LPAREN ExprList RPAREN
|
||||
///
|
||||
/// ExprList <- (Expr COMMA)* Expr?
|
||||
fn parseSuffixExpr(p: *Parse) !?Node.Index {
|
||||
if (p.eatToken(.keyword_async)) |_| {
|
||||
var res = try p.expectPrimaryTypeExpr();
|
||||
while (true) {
|
||||
res = try p.parseSuffixOp(res) orelse break;
|
||||
}
|
||||
const lparen = p.eatToken(.l_paren) orelse {
|
||||
try p.warn(.expected_param_list);
|
||||
return res;
|
||||
};
|
||||
const scratch_top = p.scratch.items.len;
|
||||
defer p.scratch.shrinkRetainingCapacity(scratch_top);
|
||||
while (true) {
|
||||
if (p.eatToken(.r_paren)) |_| break;
|
||||
const param = try p.expectExpr();
|
||||
try p.scratch.append(p.gpa, param);
|
||||
switch (p.tokenTag(p.tok_i)) {
|
||||
.comma => p.tok_i += 1,
|
||||
.r_paren => {
|
||||
p.tok_i += 1;
|
||||
break;
|
||||
},
|
||||
.colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
|
||||
// Likely just a missing comma; give error but continue parsing.
|
||||
else => try p.warn(.expected_comma_after_arg),
|
||||
}
|
||||
}
|
||||
const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
|
||||
const params = p.scratch.items[scratch_top..];
|
||||
if (params.len <= 1) {
|
||||
return try p.addNode(.{
|
||||
.tag = if (comma) .async_call_one_comma else .async_call_one,
|
||||
.main_token = lparen,
|
||||
.data = .{ .node_and_opt_node = .{
|
||||
res,
|
||||
if (params.len >= 1) params[0].toOptional() else .none,
|
||||
} },
|
||||
});
|
||||
} else {
|
||||
return try p.addNode(.{
|
||||
.tag = if (comma) .async_call_comma else .async_call,
|
||||
.main_token = lparen,
|
||||
.data = .{ .node_and_extra = .{
|
||||
res,
|
||||
try p.addExtra(try p.listToSpan(params)),
|
||||
} },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var res = try p.parsePrimaryTypeExpr() orelse return null;
|
||||
while (true) {
|
||||
const opt_suffix_op = try p.parseSuffixOp(res);
|
||||
|
||||
@ -899,8 +899,6 @@ pub const Inst = struct {
|
||||
type_name,
|
||||
/// Implement builtin `@Frame`. Uses `un_node`.
|
||||
frame_type,
|
||||
/// Implement builtin `@frameSize`. Uses `un_node`.
|
||||
frame_size,
|
||||
|
||||
/// Implements the `@intFromFloat` builtin.
|
||||
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
|
||||
@ -1044,7 +1042,6 @@ pub const Inst = struct {
|
||||
|
||||
/// Implements `resume` syntax. Uses `un_node` field.
|
||||
@"resume",
|
||||
@"await",
|
||||
|
||||
/// A defer statement.
|
||||
/// Uses the `defer` union field.
|
||||
@ -1241,7 +1238,6 @@ pub const Inst = struct {
|
||||
.tag_name,
|
||||
.type_name,
|
||||
.frame_type,
|
||||
.frame_size,
|
||||
.int_from_float,
|
||||
.float_from_int,
|
||||
.ptr_from_int,
|
||||
@ -1279,7 +1275,6 @@ pub const Inst = struct {
|
||||
.min,
|
||||
.c_import,
|
||||
.@"resume",
|
||||
.@"await",
|
||||
.ret_err_value_code,
|
||||
.extended,
|
||||
.ret_ptr,
|
||||
@ -1526,7 +1521,6 @@ pub const Inst = struct {
|
||||
.tag_name,
|
||||
.type_name,
|
||||
.frame_type,
|
||||
.frame_size,
|
||||
.int_from_float,
|
||||
.float_from_int,
|
||||
.ptr_from_int,
|
||||
@ -1560,7 +1554,6 @@ pub const Inst = struct {
|
||||
.min,
|
||||
.c_import,
|
||||
.@"resume",
|
||||
.@"await",
|
||||
.ret_err_value_code,
|
||||
.@"break",
|
||||
.break_inline,
|
||||
@ -1791,7 +1784,6 @@ pub const Inst = struct {
|
||||
.tag_name = .un_node,
|
||||
.type_name = .un_node,
|
||||
.frame_type = .un_node,
|
||||
.frame_size = .un_node,
|
||||
|
||||
.int_from_float = .pl_node,
|
||||
.float_from_int = .pl_node,
|
||||
@ -1852,7 +1844,6 @@ pub const Inst = struct {
|
||||
.make_ptr_const = .un_node,
|
||||
|
||||
.@"resume" = .un_node,
|
||||
.@"await" = .un_node,
|
||||
|
||||
.@"defer" = .@"defer",
|
||||
.defer_err_code = .defer_err_code,
|
||||
@ -2016,8 +2007,6 @@ pub const Inst = struct {
|
||||
/// Implements the `@errorCast` builtin.
|
||||
/// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand.
|
||||
error_cast,
|
||||
/// `operand` is payload index to `UnNode`.
|
||||
await_nosuspend,
|
||||
/// Implements `@breakpoint`.
|
||||
/// `operand` is `src_node: Ast.Node.Offset`.
|
||||
breakpoint,
|
||||
@ -2038,9 +2027,6 @@ pub const Inst = struct {
|
||||
/// `operand` is payload index to `Reify`.
|
||||
/// `small` contains `NameStrategy`.
|
||||
reify,
|
||||
/// Implements the `@asyncCall` builtin.
|
||||
/// `operand` is payload index to `AsyncCall`.
|
||||
builtin_async_call,
|
||||
/// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
|
||||
/// `small` 0=>weak 1=>strong
|
||||
/// `operand` is payload index to `Cmpxchg`.
|
||||
@ -2689,7 +2675,6 @@ pub const Inst = struct {
|
||||
@"test",
|
||||
decltest,
|
||||
@"comptime",
|
||||
@"usingnamespace",
|
||||
@"const",
|
||||
@"var",
|
||||
};
|
||||
@ -2706,7 +2691,7 @@ pub const Inst = struct {
|
||||
src_column: u32,
|
||||
|
||||
kind: Kind,
|
||||
/// Always `.empty` for `kind` of `unnamed_test`, `.@"comptime"`, `.@"usingnamespace"`.
|
||||
/// Always `.empty` for `kind` of `unnamed_test`, `.@"comptime"`
|
||||
name: NullTerminatedString,
|
||||
/// Always `false` for `kind` of `unnamed_test`, `.@"test"`, `.decltest`, `.@"comptime"`.
|
||||
is_pub: bool,
|
||||
@ -2737,9 +2722,6 @@ pub const Inst = struct {
|
||||
decltest,
|
||||
@"comptime",
|
||||
|
||||
@"usingnamespace",
|
||||
pub_usingnamespace,
|
||||
|
||||
const_simple,
|
||||
const_typed,
|
||||
@"const",
|
||||
@ -2776,8 +2758,6 @@ pub const Inst = struct {
|
||||
return switch (id) {
|
||||
.unnamed_test,
|
||||
.@"comptime",
|
||||
.@"usingnamespace",
|
||||
.pub_usingnamespace,
|
||||
=> false,
|
||||
else => true,
|
||||
};
|
||||
@ -2802,8 +2782,6 @@ pub const Inst = struct {
|
||||
.@"test",
|
||||
.decltest,
|
||||
.@"comptime",
|
||||
.@"usingnamespace",
|
||||
.pub_usingnamespace,
|
||||
=> false, // these constructs are untyped
|
||||
.const_simple,
|
||||
.pub_const_simple,
|
||||
@ -2835,8 +2813,6 @@ pub const Inst = struct {
|
||||
.@"test",
|
||||
.decltest,
|
||||
.@"comptime",
|
||||
.@"usingnamespace",
|
||||
.pub_usingnamespace,
|
||||
=> false, // these constructs are untyped
|
||||
.const_simple,
|
||||
.const_typed,
|
||||
@ -2879,7 +2855,6 @@ pub const Inst = struct {
|
||||
.@"test" => .@"test",
|
||||
.decltest => .decltest,
|
||||
.@"comptime" => .@"comptime",
|
||||
.@"usingnamespace", .pub_usingnamespace => .@"usingnamespace",
|
||||
.const_simple,
|
||||
.const_typed,
|
||||
.@"const",
|
||||
@ -2913,7 +2888,6 @@ pub const Inst = struct {
|
||||
|
||||
pub fn isPub(id: Id) bool {
|
||||
return switch (id) {
|
||||
.pub_usingnamespace,
|
||||
.pub_const_simple,
|
||||
.pub_const_typed,
|
||||
.pub_const,
|
||||
@ -2949,8 +2923,7 @@ pub const Inst = struct {
|
||||
|
||||
pub const Name = enum(u32) {
|
||||
@"comptime" = std.math.maxInt(u32),
|
||||
@"usingnamespace" = std.math.maxInt(u32) - 1,
|
||||
unnamed_test = std.math.maxInt(u32) - 2,
|
||||
unnamed_test = std.math.maxInt(u32) - 1,
|
||||
/// Other values are `NullTerminatedString` values, i.e. index into
|
||||
/// `string_bytes`. If the byte referenced is 0, the decl is a named
|
||||
/// test, and the actual name begins at the following byte.
|
||||
@ -2958,13 +2931,13 @@ pub const Inst = struct {
|
||||
|
||||
pub fn isNamedTest(name: Name, zir: Zir) bool {
|
||||
return switch (name) {
|
||||
.@"comptime", .@"usingnamespace", .unnamed_test => false,
|
||||
.@"comptime", .unnamed_test => false,
|
||||
_ => zir.string_bytes[@intFromEnum(name)] == 0,
|
||||
};
|
||||
}
|
||||
pub fn toString(name: Name, zir: Zir) ?NullTerminatedString {
|
||||
switch (name) {
|
||||
.@"comptime", .@"usingnamespace", .unnamed_test => return null,
|
||||
.@"comptime", .unnamed_test => return null,
|
||||
_ => {},
|
||||
}
|
||||
const idx: u32 = @intFromEnum(name);
|
||||
@ -3771,14 +3744,6 @@ pub const Inst = struct {
|
||||
b: Ref,
|
||||
};
|
||||
|
||||
pub const AsyncCall = struct {
|
||||
node: Ast.Node.Offset,
|
||||
frame_buffer: Ref,
|
||||
result_ptr: Ref,
|
||||
fn_ptr: Ref,
|
||||
args: Ref,
|
||||
};
|
||||
|
||||
/// Trailing: inst: Index // for every body_len
|
||||
pub const Param = struct {
|
||||
/// Null-terminated string index.
|
||||
@ -4297,7 +4262,6 @@ fn findTrackableInner(
|
||||
.tag_name,
|
||||
.type_name,
|
||||
.frame_type,
|
||||
.frame_size,
|
||||
.int_from_float,
|
||||
.float_from_int,
|
||||
.ptr_from_int,
|
||||
@ -4337,7 +4301,6 @@ fn findTrackableInner(
|
||||
.resolve_inferred_alloc,
|
||||
.make_ptr_const,
|
||||
.@"resume",
|
||||
.@"await",
|
||||
.save_err_ret_index,
|
||||
.restore_err_ret_index_unconditional,
|
||||
.restore_err_ret_index_fn_entry,
|
||||
@ -4380,14 +4343,12 @@ fn findTrackableInner(
|
||||
.prefetch,
|
||||
.set_float_mode,
|
||||
.error_cast,
|
||||
.await_nosuspend,
|
||||
.breakpoint,
|
||||
.disable_instrumentation,
|
||||
.disable_intrinsics,
|
||||
.select,
|
||||
.int_from_error,
|
||||
.error_from_int,
|
||||
.builtin_async_call,
|
||||
.cmpxchg,
|
||||
.c_va_arg,
|
||||
.c_va_copy,
|
||||
|
||||
@ -100,7 +100,6 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
|
||||
|
||||
switch (tree.nodeTag(node)) {
|
||||
.root => unreachable,
|
||||
.@"usingnamespace" => unreachable,
|
||||
.test_decl => unreachable,
|
||||
.container_field_init => unreachable,
|
||||
.container_field_align => unreachable,
|
||||
@ -204,12 +203,8 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
|
||||
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
.@"return",
|
||||
.if_simple,
|
||||
.@"if",
|
||||
@ -226,7 +221,6 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
|
||||
.switch_comma,
|
||||
.@"nosuspend",
|
||||
.@"suspend",
|
||||
.@"await",
|
||||
.@"resume",
|
||||
.@"try",
|
||||
.unreachable_literal,
|
||||
|
||||
@ -1521,9 +1521,9 @@ pub const Attribute = union(Kind) {
|
||||
pub const UwTable = enum(u32) {
|
||||
none,
|
||||
sync,
|
||||
@"async",
|
||||
async,
|
||||
|
||||
pub const default = UwTable.@"async";
|
||||
pub const default = UwTable.async;
|
||||
};
|
||||
|
||||
pub const VScaleRange = packed struct(u32) {
|
||||
|
||||
@ -341,15 +341,6 @@ test "zig fmt: nosuspend block" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: nosuspend await" {
|
||||
try testCanonical(
|
||||
\\fn foo() void {
|
||||
\\ x = nosuspend await y;
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: container declaration, single line" {
|
||||
try testCanonical(
|
||||
\\const X = struct { foo: i32 };
|
||||
@ -1093,18 +1084,6 @@ test "zig fmt: block in slice expression" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: async function" {
|
||||
try testCanonical(
|
||||
\\pub const Server = struct {
|
||||
\\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.@"async") void,
|
||||
\\};
|
||||
\\test "hi" {
|
||||
\\ var ptr: fn (i32) callconv(.@"async") void = @ptrCast(other);
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: whitespace fixes" {
|
||||
try testTransform("test \"\" {\r\n\tconst hi = x;\r\n}\n// zig fmt: off\ntest \"\"{\r\n\tconst a = b;}\r\n",
|
||||
\\test "" {
|
||||
@ -1549,17 +1528,6 @@ test "zig fmt: spaces around slice operator" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: async call in if condition" {
|
||||
try testCanonical(
|
||||
\\comptime {
|
||||
\\ if (async b()) {
|
||||
\\ a();
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: 2nd arg multiline string" {
|
||||
try testCanonical(
|
||||
\\comptime {
|
||||
@ -3946,27 +3914,6 @@ test "zig fmt: inline asm" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: async functions" {
|
||||
try testCanonical(
|
||||
\\fn simpleAsyncFn() void {
|
||||
\\ const a = async a.b();
|
||||
\\ x += 1;
|
||||
\\ suspend {}
|
||||
\\ x += 1;
|
||||
\\ suspend {}
|
||||
\\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
|
||||
\\ await p;
|
||||
\\}
|
||||
\\
|
||||
\\test "suspend, resume, await" {
|
||||
\\ const p: anyframe = async testAsyncSeq();
|
||||
\\ resume p;
|
||||
\\ await p;
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: nosuspend" {
|
||||
try testCanonical(
|
||||
\\const a = nosuspend foo();
|
||||
@ -3989,14 +3936,6 @@ test "zig fmt: Block after if" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: usingnamespace" {
|
||||
try testCanonical(
|
||||
\\usingnamespace @import("std");
|
||||
\\pub usingnamespace @import("std");
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: string identifier" {
|
||||
try testCanonical(
|
||||
\\const @"a b" = @"c d".@"e f";
|
||||
@ -5140,17 +5079,6 @@ test "zig fmt: line comment after multiline single expr if statement with multil
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: respect extra newline between fn and pub usingnamespace" {
|
||||
try testCanonical(
|
||||
\\fn foo() void {
|
||||
\\ bar();
|
||||
\\}
|
||||
\\
|
||||
\\pub usingnamespace baz;
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: respect extra newline between switch items" {
|
||||
try testCanonical(
|
||||
\\const a = switch (b) {
|
||||
@ -5719,34 +5647,6 @@ test "zig fmt: canonicalize symbols (primitive types)" {
|
||||
);
|
||||
}
|
||||
|
||||
// Never unescape names spelled like keywords.
|
||||
test "zig fmt: canonicalize symbols (keywords)" {
|
||||
try testCanonical(
|
||||
\\const @"enum" = struct {
|
||||
\\ @"error": @"struct" = true,
|
||||
\\ const @"struct" = bool;
|
||||
\\};
|
||||
\\
|
||||
\\fn @"usingnamespace"(@"union": @"enum") error{@"try"}!void {
|
||||
\\ var @"struct" = @"union";
|
||||
\\ @"struct".@"error" = false;
|
||||
\\ if (@"struct".@"error") {
|
||||
\\ return @"usingnamespace"(.{ .@"error" = false });
|
||||
\\ } else {
|
||||
\\ return error.@"try";
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
\\test @"usingnamespace" {
|
||||
\\ try @"usingnamespace"(.{});
|
||||
\\ _ = @"return": {
|
||||
\\ break :@"return" 4;
|
||||
\\ };
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: no space before newline before multiline string" {
|
||||
try testCanonical(
|
||||
\\const S = struct {
|
||||
@ -6181,29 +6081,6 @@ test "recovery: missing return type" {
|
||||
});
|
||||
}
|
||||
|
||||
test "recovery: continue after invalid decl" {
|
||||
try testError(
|
||||
\\fn foo {
|
||||
\\ inline;
|
||||
\\}
|
||||
\\pub test "" {
|
||||
\\ async a & b;
|
||||
\\}
|
||||
, &[_]Error{
|
||||
.expected_token,
|
||||
.expected_pub_item,
|
||||
.expected_param_list,
|
||||
});
|
||||
try testError(
|
||||
\\threadlocal test "" {
|
||||
\\ @a & b;
|
||||
\\}
|
||||
, &[_]Error{
|
||||
.expected_var_decl,
|
||||
.expected_param_list,
|
||||
});
|
||||
}
|
||||
|
||||
test "recovery: invalid extern/inline" {
|
||||
try testError(
|
||||
\\inline test "" { a & b; }
|
||||
@ -6232,22 +6109,6 @@ test "recovery: missing semicolon" {
|
||||
});
|
||||
}
|
||||
|
||||
test "recovery: invalid container members" {
|
||||
try testError(
|
||||
\\usingnamespace;
|
||||
\\@foo()+
|
||||
\\@bar()@,
|
||||
\\while (a == 2) { test "" {}}
|
||||
\\test "" {
|
||||
\\ a & b
|
||||
\\}
|
||||
, &[_]Error{
|
||||
.expected_expr,
|
||||
.expected_comma_after_field,
|
||||
.expected_semi_after_stmt,
|
||||
});
|
||||
}
|
||||
|
||||
// TODO after https://github.com/ziglang/zig/issues/35 is implemented,
|
||||
// we should be able to recover from this *at any indentation level*,
|
||||
// reporting a parse error and yet also parsing all the decls even
|
||||
|
||||
@ -262,17 +262,6 @@ fn renderMember(
|
||||
return renderToken(r, tree.lastToken(decl) + 1, space); // semicolon
|
||||
},
|
||||
|
||||
.@"usingnamespace" => {
|
||||
const main_token = tree.nodeMainToken(decl);
|
||||
const expr = tree.nodeData(decl).node;
|
||||
if (tree.isTokenPrecededByTags(main_token, &.{.keyword_pub})) {
|
||||
try renderToken(r, main_token - 1, .space); // pub
|
||||
}
|
||||
try renderToken(r, main_token, .space); // usingnamespace
|
||||
try renderExpression(r, expr, .none);
|
||||
return renderToken(r, tree.lastToken(expr) + 1, space); // ;
|
||||
},
|
||||
|
||||
.global_var_decl,
|
||||
.local_var_decl,
|
||||
.simple_var_decl,
|
||||
@ -591,7 +580,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
||||
|
||||
.@"try",
|
||||
.@"resume",
|
||||
.@"await",
|
||||
=> {
|
||||
try renderToken(r, tree.nodeMainToken(node), .space);
|
||||
return renderExpression(r, tree.nodeData(node).node, space);
|
||||
@ -635,12 +623,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
||||
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> {
|
||||
var buf: [1]Ast.Node.Index = undefined;
|
||||
return renderCall(r, tree.fullCall(&buf, node).?, space);
|
||||
@ -882,7 +866,6 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
||||
.local_var_decl => unreachable,
|
||||
.simple_var_decl => unreachable,
|
||||
.aligned_var_decl => unreachable,
|
||||
.@"usingnamespace" => unreachable,
|
||||
.test_decl => unreachable,
|
||||
.asm_output => unreachable,
|
||||
.asm_input => unreachable,
|
||||
@ -2551,9 +2534,6 @@ fn renderCall(
|
||||
call: Ast.full.Call,
|
||||
space: Space,
|
||||
) Error!void {
|
||||
if (call.async_token) |async_token| {
|
||||
try renderToken(r, async_token, .space);
|
||||
}
|
||||
try renderExpression(r, call.ast.fn_expr, .none);
|
||||
try renderParamList(r, call.ast.lparen, call.ast.params, space);
|
||||
}
|
||||
|
||||
@ -17,8 +17,6 @@ pub const Token = struct {
|
||||
.{ "anyframe", .keyword_anyframe },
|
||||
.{ "anytype", .keyword_anytype },
|
||||
.{ "asm", .keyword_asm },
|
||||
.{ "async", .keyword_async },
|
||||
.{ "await", .keyword_await },
|
||||
.{ "break", .keyword_break },
|
||||
.{ "callconv", .keyword_callconv },
|
||||
.{ "catch", .keyword_catch },
|
||||
@ -55,7 +53,6 @@ pub const Token = struct {
|
||||
.{ "try", .keyword_try },
|
||||
.{ "union", .keyword_union },
|
||||
.{ "unreachable", .keyword_unreachable },
|
||||
.{ "usingnamespace", .keyword_usingnamespace },
|
||||
.{ "var", .keyword_var },
|
||||
.{ "volatile", .keyword_volatile },
|
||||
.{ "while", .keyword_while },
|
||||
@ -146,8 +143,6 @@ pub const Token = struct {
|
||||
keyword_anyframe,
|
||||
keyword_anytype,
|
||||
keyword_asm,
|
||||
keyword_async,
|
||||
keyword_await,
|
||||
keyword_break,
|
||||
keyword_callconv,
|
||||
keyword_catch,
|
||||
@ -184,7 +179,6 @@ pub const Token = struct {
|
||||
keyword_try,
|
||||
keyword_union,
|
||||
keyword_unreachable,
|
||||
keyword_usingnamespace,
|
||||
keyword_var,
|
||||
keyword_volatile,
|
||||
keyword_while,
|
||||
@ -273,8 +267,6 @@ pub const Token = struct {
|
||||
.keyword_anyframe => "anyframe",
|
||||
.keyword_anytype => "anytype",
|
||||
.keyword_asm => "asm",
|
||||
.keyword_async => "async",
|
||||
.keyword_await => "await",
|
||||
.keyword_break => "break",
|
||||
.keyword_callconv => "callconv",
|
||||
.keyword_catch => "catch",
|
||||
@ -311,7 +303,6 @@ pub const Token = struct {
|
||||
.keyword_try => "try",
|
||||
.keyword_union => "union",
|
||||
.keyword_unreachable => "unreachable",
|
||||
.keyword_usingnamespace => "usingnamespace",
|
||||
.keyword_var => "var",
|
||||
.keyword_volatile => "volatile",
|
||||
.keyword_while => "while",
|
||||
|
||||
@ -6466,7 +6466,7 @@ pub fn addCCArgs(
|
||||
try argv.append("-fno-asynchronous-unwind-tables");
|
||||
try argv.append("-funwind-tables");
|
||||
},
|
||||
.@"async" => try argv.append("-fasynchronous-unwind-tables"),
|
||||
.async => try argv.append("-fasynchronous-unwind-tables"),
|
||||
}
|
||||
|
||||
try argv.append("-nostdinc");
|
||||
|
||||
@ -518,8 +518,6 @@ pub const Nav = struct {
|
||||
namespace: NamespaceIndex,
|
||||
zir_index: TrackedInst.Index,
|
||||
},
|
||||
/// TODO: this is a hack! If #20663 isn't accepted, let's figure out something a bit better.
|
||||
is_usingnamespace: bool,
|
||||
status: union(enum) {
|
||||
/// This `Nav` is pending semantic analysis.
|
||||
unresolved,
|
||||
@ -735,7 +733,7 @@ pub const Nav = struct {
|
||||
@"addrspace": std.builtin.AddressSpace,
|
||||
/// Populated only if `bits.status == .type_resolved`.
|
||||
is_threadlocal: bool,
|
||||
is_usingnamespace: bool,
|
||||
_: u1 = 0,
|
||||
};
|
||||
|
||||
fn unpack(repr: Repr) Nav {
|
||||
@ -749,7 +747,6 @@ pub const Nav = struct {
|
||||
assert(repr.analysis_zir_index == .none);
|
||||
break :a null;
|
||||
},
|
||||
.is_usingnamespace = repr.bits.is_usingnamespace,
|
||||
.status = switch (repr.bits.status) {
|
||||
.unresolved => .unresolved,
|
||||
.type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{
|
||||
@ -797,7 +794,6 @@ pub const Nav = struct {
|
||||
.is_const = false,
|
||||
.alignment = .none,
|
||||
.@"addrspace" = .generic,
|
||||
.is_usingnamespace = nav.is_usingnamespace,
|
||||
.is_threadlocal = false,
|
||||
},
|
||||
.type_resolved => |r| .{
|
||||
@ -805,7 +801,6 @@ pub const Nav = struct {
|
||||
.is_const = r.is_const,
|
||||
.alignment = r.alignment,
|
||||
.@"addrspace" = r.@"addrspace",
|
||||
.is_usingnamespace = nav.is_usingnamespace,
|
||||
.is_threadlocal = r.is_threadlocal,
|
||||
},
|
||||
.fully_resolved => |r| .{
|
||||
@ -813,7 +808,6 @@ pub const Nav = struct {
|
||||
.is_const = r.is_const,
|
||||
.alignment = r.alignment,
|
||||
.@"addrspace" = r.@"addrspace",
|
||||
.is_usingnamespace = nav.is_usingnamespace,
|
||||
.is_threadlocal = false,
|
||||
},
|
||||
},
|
||||
@ -6865,8 +6859,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
|
||||
{
|
||||
namespace.pub_decls.deinit(gpa);
|
||||
namespace.priv_decls.deinit(gpa);
|
||||
namespace.pub_usingnamespace.deinit(gpa);
|
||||
namespace.priv_usingnamespace.deinit(gpa);
|
||||
namespace.comptime_decls.deinit(gpa);
|
||||
namespace.test_decls.deinit(gpa);
|
||||
}
|
||||
@ -11503,7 +11495,6 @@ pub fn createNav(
|
||||
.@"linksection" = opts.@"linksection",
|
||||
.@"addrspace" = opts.@"addrspace",
|
||||
} },
|
||||
.is_usingnamespace = false,
|
||||
}));
|
||||
return index_unwrapped.wrap(ip);
|
||||
}
|
||||
@ -11518,8 +11509,6 @@ pub fn createDeclNav(
|
||||
fqn: NullTerminatedString,
|
||||
zir_index: TrackedInst.Index,
|
||||
namespace: NamespaceIndex,
|
||||
/// TODO: this is hacky! See `Nav.is_usingnamespace`.
|
||||
is_usingnamespace: bool,
|
||||
) Allocator.Error!Nav.Index {
|
||||
const navs = ip.getLocal(tid).getMutableNavs(gpa);
|
||||
|
||||
@ -11538,7 +11527,6 @@ pub fn createDeclNav(
|
||||
.zir_index = zir_index,
|
||||
},
|
||||
.status = .unresolved,
|
||||
.is_usingnamespace = is_usingnamespace,
|
||||
}));
|
||||
|
||||
return nav;
|
||||
|
||||
174
src/Sema.zig
174
src/Sema.zig
@ -1280,7 +1280,6 @@ fn analyzeBodyInner(
|
||||
.tag_name => try sema.zirTagName(block, inst),
|
||||
.type_name => try sema.zirTypeName(block, inst),
|
||||
.frame_type => try sema.zirFrameType(block, inst),
|
||||
.frame_size => try sema.zirFrameSize(block, inst),
|
||||
.int_from_float => try sema.zirIntFromFloat(block, inst),
|
||||
.float_from_int => try sema.zirFloatFromInt(block, inst),
|
||||
.ptr_from_int => try sema.zirPtrFromInt(block, inst),
|
||||
@ -1302,7 +1301,6 @@ fn analyzeBodyInner(
|
||||
.mul_add => try sema.zirMulAdd(block, inst),
|
||||
.builtin_call => try sema.zirBuiltinCall(block, inst),
|
||||
.@"resume" => try sema.zirResume(block, inst),
|
||||
.@"await" => try sema.zirAwait(block, inst),
|
||||
.for_len => try sema.zirForLen(block, inst),
|
||||
.validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst),
|
||||
.opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst),
|
||||
@ -1410,12 +1408,10 @@ fn analyzeBodyInner(
|
||||
.wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended),
|
||||
.prefetch => try sema.zirPrefetch( block, extended),
|
||||
.error_cast => try sema.zirErrorCast( block, extended),
|
||||
.await_nosuspend => try sema.zirAwaitNosuspend( block, extended),
|
||||
.select => try sema.zirSelect( block, extended),
|
||||
.int_from_error => try sema.zirIntFromError( block, extended),
|
||||
.error_from_int => try sema.zirErrorFromInt( block, extended),
|
||||
.reify => try sema.zirReify( block, extended, inst),
|
||||
.builtin_async_call => try sema.zirBuiltinAsyncCall( block, extended),
|
||||
.cmpxchg => try sema.zirCmpxchg( block, extended),
|
||||
.c_va_arg => try sema.zirCVaArg( block, extended),
|
||||
.c_va_copy => try sema.zirCVaCopy( block, extended),
|
||||
@ -2864,7 +2860,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
|
||||
sema.code.nullTerminatedString(str),
|
||||
.no_embedded_nulls,
|
||||
);
|
||||
const nav = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc?
|
||||
const nav = try sema.lookupIdentifier(block, decl_name);
|
||||
break :capture InternPool.CaptureValue.wrap(.{ .nav_val = nav });
|
||||
},
|
||||
.decl_ref => |str| capture: {
|
||||
@ -2874,7 +2870,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
|
||||
sema.code.nullTerminatedString(str),
|
||||
.no_embedded_nulls,
|
||||
);
|
||||
const nav = try sema.lookupIdentifier(block, LazySrcLoc.unneeded, decl_name); // TODO: could we need this src loc?
|
||||
const nav = try sema.lookupIdentifier(block, decl_name);
|
||||
break :capture InternPool.CaptureValue.wrap(.{ .nav_ref = nav });
|
||||
},
|
||||
};
|
||||
@ -6929,7 +6925,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
inst_data.get(sema.code),
|
||||
.no_embedded_nulls,
|
||||
);
|
||||
const nav_index = try sema.lookupIdentifier(block, src, decl_name);
|
||||
const nav_index = try sema.lookupIdentifier(block, decl_name);
|
||||
return sema.analyzeNavRef(block, src, nav_index);
|
||||
}
|
||||
|
||||
@ -6944,16 +6940,16 @@ fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
inst_data.get(sema.code),
|
||||
.no_embedded_nulls,
|
||||
);
|
||||
const nav = try sema.lookupIdentifier(block, src, decl_name);
|
||||
const nav = try sema.lookupIdentifier(block, decl_name);
|
||||
return sema.analyzeNavVal(block, src, nav);
|
||||
}
|
||||
|
||||
fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: InternPool.NullTerminatedString) !InternPool.Nav.Index {
|
||||
fn lookupIdentifier(sema: *Sema, block: *Block, name: InternPool.NullTerminatedString) !InternPool.Nav.Index {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
var namespace = block.namespace;
|
||||
while (true) {
|
||||
if (try sema.lookupInNamespace(block, src, namespace, name, false)) |lookup| {
|
||||
if (try sema.lookupInNamespace(block, namespace, name)) |lookup| {
|
||||
assert(lookup.accessible);
|
||||
return lookup.nav;
|
||||
}
|
||||
@ -6962,15 +6958,12 @@ fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: InternPoo
|
||||
unreachable; // AstGen detects use of undeclared identifiers.
|
||||
}
|
||||
|
||||
/// This looks up a member of a specific namespace. It is affected by `usingnamespace` but
|
||||
/// only for ones in the specified namespace.
|
||||
/// This looks up a member of a specific namespace.
|
||||
fn lookupInNamespace(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
namespace_index: InternPool.NamespaceIndex,
|
||||
ident_name: InternPool.NullTerminatedString,
|
||||
observe_usingnamespace: bool,
|
||||
) CompileError!?struct {
|
||||
nav: InternPool.Nav.Index,
|
||||
/// If `false`, the declaration is in a different file and is not `pub`.
|
||||
@ -6979,7 +6972,6 @@ fn lookupInNamespace(
|
||||
} {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
try pt.ensureNamespaceUpToDate(namespace_index);
|
||||
|
||||
@ -6996,75 +6988,7 @@ fn lookupInNamespace(
|
||||
} });
|
||||
}
|
||||
|
||||
if (observe_usingnamespace and (namespace.pub_usingnamespace.items.len != 0 or namespace.priv_usingnamespace.items.len != 0)) {
|
||||
const gpa = sema.gpa;
|
||||
var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .empty;
|
||||
defer checked_namespaces.deinit(gpa);
|
||||
|
||||
// Keep track of name conflicts for error notes.
|
||||
var candidates: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty;
|
||||
defer candidates.deinit(gpa);
|
||||
|
||||
try checked_namespaces.put(gpa, namespace, {});
|
||||
var check_i: usize = 0;
|
||||
|
||||
while (check_i < checked_namespaces.count()) : (check_i += 1) {
|
||||
const check_ns = checked_namespaces.keys()[check_i];
|
||||
const Pass = enum { @"pub", priv };
|
||||
for ([2]Pass{ .@"pub", .priv }) |pass| {
|
||||
if (pass == .priv and src_file != check_ns.file_scope) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const decls, const usingnamespaces = switch (pass) {
|
||||
.@"pub" => .{ &check_ns.pub_decls, &check_ns.pub_usingnamespace },
|
||||
.priv => .{ &check_ns.priv_decls, &check_ns.priv_usingnamespace },
|
||||
};
|
||||
|
||||
if (decls.getKeyAdapted(ident_name, adapter)) |nav_index| {
|
||||
try candidates.append(gpa, nav_index);
|
||||
}
|
||||
|
||||
for (usingnamespaces.items) |sub_ns_nav| {
|
||||
try sema.ensureNavResolved(block, src, sub_ns_nav, .fully);
|
||||
const sub_ns_ty: Type = .fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val);
|
||||
const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu));
|
||||
try checked_namespaces.put(gpa, sub_ns, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ignore_self: {
|
||||
const skip_nav = switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .type, .func, .memoized_state => break :ignore_self,
|
||||
.nav_ty, .nav_val => |nav| nav,
|
||||
};
|
||||
var i: usize = 0;
|
||||
while (i < candidates.items.len) {
|
||||
if (candidates.items[i] == skip_nav) {
|
||||
_ = candidates.orderedRemove(i);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (candidates.items.len) {
|
||||
0 => {},
|
||||
1 => return .{
|
||||
.nav = candidates.items[0],
|
||||
.accessible = true,
|
||||
},
|
||||
else => return sema.failWithOwnedErrorMsg(block, msg: {
|
||||
const msg = try sema.errMsg(src, "ambiguous reference", .{});
|
||||
errdefer msg.destroy(gpa);
|
||||
for (candidates.items) |candidate| {
|
||||
try sema.errNote(zcu.navSrcLoc(candidate), msg, "declared here", .{});
|
||||
}
|
||||
break :msg msg;
|
||||
}),
|
||||
}
|
||||
} else if (namespace.pub_decls.getKeyAdapted(ident_name, adapter)) |nav_index| {
|
||||
if (namespace.pub_decls.getKeyAdapted(ident_name, adapter)) |nav_index| {
|
||||
return .{
|
||||
.nav = nav_index,
|
||||
.accessible = true,
|
||||
@ -7653,10 +7577,6 @@ fn analyzeCall(
|
||||
const ip = &zcu.intern_pool;
|
||||
const arena = sema.arena;
|
||||
|
||||
if (modifier == .async_kw) {
|
||||
return sema.failWithUseOfAsync(block, call_src);
|
||||
}
|
||||
|
||||
const maybe_func_inst = try sema.funcDeclSrcInst(callee);
|
||||
const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{
|
||||
.base_node_inst = fn_decl_inst,
|
||||
@ -8048,14 +7968,13 @@ fn analyzeCall(
|
||||
}
|
||||
|
||||
const call_tag: Air.Inst.Tag = switch (modifier) {
|
||||
.auto, .no_async => .call,
|
||||
.auto, .no_suspend => .call,
|
||||
.never_tail => .call_never_tail,
|
||||
.never_inline => .call_never_inline,
|
||||
.always_tail => .call_always_tail,
|
||||
|
||||
.always_inline,
|
||||
.compile_time,
|
||||
.async_kw,
|
||||
=> unreachable,
|
||||
};
|
||||
|
||||
@ -13955,7 +13874,6 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const zcu = pt.zcu;
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
|
||||
const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
|
||||
const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
|
||||
@ -13964,7 +13882,7 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
try sema.checkNamespaceType(block, lhs_src, container_type);
|
||||
|
||||
const namespace = container_type.getNamespace(zcu).unwrap() orelse return .bool_false;
|
||||
if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |lookup| {
|
||||
if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| {
|
||||
if (lookup.accessible) {
|
||||
return .bool_true;
|
||||
}
|
||||
@ -17745,7 +17663,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ip.loadEnumType(ty.toIntern()).namespace.toOptional());
|
||||
const decls_val = try sema.typeInfoDecls(src, ip.loadEnumType(ty.toIntern()).namespace.toOptional());
|
||||
|
||||
const type_enum_ty = try sema.getBuiltinType(src, .@"Type.Enum");
|
||||
|
||||
@ -17858,7 +17776,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ty.getNamespaceIndex(zcu).toOptional());
|
||||
const decls_val = try sema.typeInfoDecls(src, ty.getNamespaceIndex(zcu).toOptional());
|
||||
|
||||
const enum_tag_ty_val = try pt.intern(.{ .opt = .{
|
||||
.ty = (try pt.optionalType(.type_type)).toIntern(),
|
||||
@ -18053,7 +17971,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ty.getNamespace(zcu));
|
||||
const decls_val = try sema.typeInfoDecls(src, ty.getNamespace(zcu));
|
||||
|
||||
const backing_integer_val = try pt.intern(.{ .opt = .{
|
||||
.ty = (try pt.optionalType(.type_type)).toIntern(),
|
||||
@ -18092,7 +18010,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const type_opaque_ty = try sema.getBuiltinType(src, .@"Type.Opaque");
|
||||
|
||||
try ty.resolveFields(pt);
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ty.getNamespace(zcu));
|
||||
const decls_val = try sema.typeInfoDecls(src, ty.getNamespace(zcu));
|
||||
|
||||
const field_values = .{
|
||||
// decls: []const Declaration,
|
||||
@ -18114,7 +18032,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
|
||||
fn typeInfoDecls(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
opt_namespace: InternPool.OptionalNamespaceIndex,
|
||||
) CompileError!InternPool.Index {
|
||||
@ -18130,7 +18047,7 @@ fn typeInfoDecls(
|
||||
var seen_namespaces = std.AutoHashMap(*Namespace, void).init(gpa);
|
||||
defer seen_namespaces.deinit();
|
||||
|
||||
try sema.typeInfoNamespaceDecls(block, src, opt_namespace, declaration_ty, &decl_vals, &seen_namespaces);
|
||||
try sema.typeInfoNamespaceDecls(opt_namespace, declaration_ty, &decl_vals, &seen_namespaces);
|
||||
|
||||
const array_decl_ty = try pt.arrayType(.{
|
||||
.len = decl_vals.items.len,
|
||||
@ -18164,8 +18081,6 @@ fn typeInfoDecls(
|
||||
|
||||
fn typeInfoNamespaceDecls(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
opt_namespace_index: InternPool.OptionalNamespaceIndex,
|
||||
declaration_ty: Type,
|
||||
decl_vals: *std.ArrayList(InternPool.Index),
|
||||
@ -18221,15 +18136,6 @@ fn typeInfoNamespaceDecls(
|
||||
.storage = .{ .elems = &fields },
|
||||
} }));
|
||||
}
|
||||
|
||||
for (namespace.pub_usingnamespace.items) |nav| {
|
||||
if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) {
|
||||
continue;
|
||||
}
|
||||
try sema.ensureNavResolved(block, src, nav, .fully);
|
||||
const namespace_ty: Type = .fromInterned(ip.getNav(nav).status.fully_resolved.val);
|
||||
try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces);
|
||||
}
|
||||
}
|
||||
|
||||
fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
@ -22133,12 +22039,6 @@ fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
return sema.failWithUseOfAsync(block, src);
|
||||
}
|
||||
|
||||
fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
return sema.failWithUseOfAsync(block, src);
|
||||
}
|
||||
|
||||
fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
@ -24776,14 +24676,14 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
var modifier = try sema.interpretBuiltinType(block, modifier_src, modifier_val, std.builtin.CallModifier);
|
||||
switch (modifier) {
|
||||
// These can be upgraded to comptime or nosuspend calls.
|
||||
.auto, .never_tail, .no_async => {
|
||||
.auto, .never_tail, .no_suspend => {
|
||||
if (block.isComptime()) {
|
||||
if (modifier == .never_tail) {
|
||||
return sema.fail(block, modifier_src, "unable to perform 'never_tail' call at compile-time", .{});
|
||||
}
|
||||
modifier = .compile_time;
|
||||
} else if (extra.flags.is_nosuspend) {
|
||||
modifier = .no_async;
|
||||
modifier = .no_suspend;
|
||||
}
|
||||
},
|
||||
// These can be upgraded to comptime. nosuspend bit can be safely ignored.
|
||||
@ -24801,14 +24701,6 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
modifier = .compile_time;
|
||||
}
|
||||
},
|
||||
.async_kw => {
|
||||
if (extra.flags.is_nosuspend) {
|
||||
return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{});
|
||||
}
|
||||
if (block.isComptime()) {
|
||||
return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{});
|
||||
}
|
||||
},
|
||||
.never_inline => {
|
||||
if (block.isComptime()) {
|
||||
return sema.fail(block, modifier_src, "unable to perform 'never_inline' call at compile-time", .{});
|
||||
@ -25797,40 +25689,12 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
|
||||
});
|
||||
}
|
||||
|
||||
fn zirBuiltinAsyncCall(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
|
||||
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||
const src = block.nodeOffset(extra.node);
|
||||
return sema.failWithUseOfAsync(block, src);
|
||||
}
|
||||
|
||||
fn zirResume(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
return sema.failWithUseOfAsync(block, src);
|
||||
}
|
||||
|
||||
fn zirAwait(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
inst: Zir.Inst.Index,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
|
||||
return sema.failWithUseOfAsync(block, src);
|
||||
}
|
||||
|
||||
fn zirAwaitNosuspend(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
extended: Zir.Inst.Extended.InstData,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||
const src = block.nodeOffset(extra.node);
|
||||
|
||||
return sema.failWithUseOfAsync(block, src);
|
||||
}
|
||||
|
||||
fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
@ -26738,7 +26602,7 @@ fn explainWhyTypeIsNotExtern(
|
||||
}
|
||||
switch (ty.fnCallingConvention(zcu)) {
|
||||
.auto => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}),
|
||||
.@"async" => try sema.errNote(src_loc, msg, "async function cannot be extern", .{}),
|
||||
.async => try sema.errNote(src_loc, msg, "async function cannot be extern", .{}),
|
||||
.@"inline" => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}),
|
||||
else => return,
|
||||
}
|
||||
@ -27760,7 +27624,7 @@ fn namespaceLookup(
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const gpa = sema.gpa;
|
||||
if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |lookup| {
|
||||
if (try sema.lookupInNamespace(block, namespace, decl_name)) |lookup| {
|
||||
if (!lookup.accessible) {
|
||||
return sema.failWithOwnedErrorMsg(block, msg: {
|
||||
const msg = try sema.errMsg(src, "'{}' is not marked 'pub'", .{
|
||||
|
||||
@ -382,7 +382,7 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
|
||||
}
|
||||
}
|
||||
switch (fn_info.cc) {
|
||||
.auto, .@"async", .naked, .@"inline" => try writer.print("callconv(.{}) ", .{std.zig.fmtId(@tagName(fn_info.cc))}),
|
||||
.auto, .async, .naked, .@"inline" => try writer.print("callconv(.{}) ", .{std.zig.fmtId(@tagName(fn_info.cc))}),
|
||||
else => try writer.print("callconv({any}) ", .{fn_info.cc}),
|
||||
}
|
||||
}
|
||||
|
||||
35
src/Zcu.zig
35
src/Zcu.zig
@ -792,10 +792,6 @@ pub const Namespace = struct {
|
||||
pub_decls: std.ArrayHashMapUnmanaged(InternPool.Nav.Index, void, NavNameContext, true) = .empty,
|
||||
/// Members of the namespace which are *not* marked `pub`.
|
||||
priv_decls: std.ArrayHashMapUnmanaged(InternPool.Nav.Index, void, NavNameContext, true) = .empty,
|
||||
/// All `usingnamespace` declarations in this namespace which are marked `pub`.
|
||||
pub_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
|
||||
/// All `usingnamespace` declarations in this namespace which are *not* marked `pub`.
|
||||
priv_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
|
||||
/// All `comptime` declarations in this namespace. We store these purely so that incremental
|
||||
/// compilation can re-use the existing `ComptimeUnit`s when a namespace changes.
|
||||
comptime_decls: std.ArrayListUnmanaged(InternPool.ComptimeUnit.Id) = .empty,
|
||||
@ -1303,9 +1299,6 @@ pub const SrcLoc = struct {
|
||||
.simple_var_decl,
|
||||
.aligned_var_decl,
|
||||
=> tree.fullVarDecl(node).?,
|
||||
.@"usingnamespace" => {
|
||||
return tree.nodeToSpan(tree.nodeData(node).node);
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
if (full.ast.type_node.unwrap()) |type_node| {
|
||||
@ -1443,12 +1436,8 @@ pub const SrcLoc = struct {
|
||||
.field_access => tree.nodeData(node).node_and_token[1],
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.call,
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
=> blk: {
|
||||
const full = tree.fullCall(&buf, node).?;
|
||||
break :blk tree.lastToken(full.ast.fn_expr);
|
||||
@ -3395,9 +3384,6 @@ pub fn mapOldZirToNew(
|
||||
// All comptime declarations, in order, for a best-effort match.
|
||||
var comptime_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .empty;
|
||||
defer comptime_decls.deinit(gpa);
|
||||
// All usingnamespace declarations, in order, for a best-effort match.
|
||||
var usingnamespace_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .empty;
|
||||
defer usingnamespace_decls.deinit(gpa);
|
||||
|
||||
{
|
||||
var old_decl_it = old_zir.declIterator(match_item.old_inst);
|
||||
@ -3405,7 +3391,6 @@ pub fn mapOldZirToNew(
|
||||
const old_decl = old_zir.getDeclaration(old_decl_inst);
|
||||
switch (old_decl.kind) {
|
||||
.@"comptime" => try comptime_decls.append(gpa, old_decl_inst),
|
||||
.@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst),
|
||||
.unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),
|
||||
.@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
|
||||
.decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
|
||||
@ -3416,7 +3401,6 @@ pub fn mapOldZirToNew(
|
||||
|
||||
var unnamed_test_idx: u32 = 0;
|
||||
var comptime_decl_idx: u32 = 0;
|
||||
var usingnamespace_decl_idx: u32 = 0;
|
||||
|
||||
var new_decl_it = new_zir.declIterator(match_item.new_inst);
|
||||
while (new_decl_it.next()) |new_decl_inst| {
|
||||
@ -3426,7 +3410,6 @@ pub fn mapOldZirToNew(
|
||||
// * For named tests (`test "foo"`) and decltests (`test foo`), we also match based on name.
|
||||
// * For unnamed tests, we match based on order.
|
||||
// * For comptime blocks, we match based on order.
|
||||
// * For usingnamespace decls, we match based on order.
|
||||
// If we cannot match this declaration, we can't match anything nested inside of it either, so we just `continue`.
|
||||
const old_decl_inst = switch (new_decl.kind) {
|
||||
.@"comptime" => inst: {
|
||||
@ -3434,11 +3417,6 @@ pub fn mapOldZirToNew(
|
||||
defer comptime_decl_idx += 1;
|
||||
break :inst comptime_decls.items[comptime_decl_idx];
|
||||
},
|
||||
.@"usingnamespace" => inst: {
|
||||
if (usingnamespace_decl_idx == usingnamespace_decls.items.len) continue;
|
||||
defer usingnamespace_decl_idx += 1;
|
||||
break :inst usingnamespace_decls.items[usingnamespace_decl_idx];
|
||||
},
|
||||
.unnamed_test => inst: {
|
||||
if (unnamed_test_idx == unnamed_tests.items.len) continue;
|
||||
defer unnamed_test_idx += 1;
|
||||
@ -4147,7 +4125,6 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
|
||||
if (!comp.config.is_test or file.mod != zcu.main_mod) continue;
|
||||
|
||||
const want_analysis = switch (decl.kind) {
|
||||
.@"usingnamespace" => unreachable,
|
||||
.@"const", .@"var" => unreachable,
|
||||
.@"comptime" => unreachable,
|
||||
.unnamed_test => true,
|
||||
@ -4205,16 +4182,6 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
|
||||
}
|
||||
}
|
||||
}
|
||||
// Incremental compilation does not support `usingnamespace`.
|
||||
// These are only included to keep good reference traces in non-incremental updates.
|
||||
for (zcu.namespacePtr(ns).pub_usingnamespace.items) |nav| {
|
||||
const unit: AnalUnit = .wrap(.{ .nav_val = nav });
|
||||
if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
|
||||
}
|
||||
for (zcu.namespacePtr(ns).priv_usingnamespace.items) |nav| {
|
||||
const unit: AnalUnit = .wrap(.{ .nav_val = nav });
|
||||
if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (unit_queue.pop()) |kv| {
|
||||
@ -4457,7 +4424,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu
|
||||
const backend = target_util.zigBackend(target, zcu.comp.config.use_llvm);
|
||||
switch (cc) {
|
||||
.auto, .@"inline" => return .ok,
|
||||
.@"async" => return .{ .bad_backend = backend }, // nothing supports async currently
|
||||
.async => return .{ .bad_backend = backend }, // nothing supports async currently
|
||||
.naked => {}, // depends only on backend
|
||||
else => for (cc.archs()) |allowed_arch| {
|
||||
if (allowed_arch == target.cpu.arch) break;
|
||||
|
||||
@ -1111,7 +1111,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
|
||||
defer block.instructions.deinit(gpa);
|
||||
|
||||
const zir_decl = zir.getDeclaration(inst_resolved.inst);
|
||||
assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
|
||||
|
||||
const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero });
|
||||
const init_src = block.src(.{ .node_offset_var_decl_init = .zero });
|
||||
@ -1160,7 +1159,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
|
||||
assert(nav_ty.zigTypeTag(zcu) == .@"fn");
|
||||
break :is_const true;
|
||||
},
|
||||
.@"usingnamespace", .@"const" => true,
|
||||
.@"const" => true,
|
||||
.@"var" => {
|
||||
try sema.validateVarType(
|
||||
&block,
|
||||
@ -1240,26 +1239,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
|
||||
// this resolves the type `type` (which needs no resolution), not the struct itself.
|
||||
try nav_ty.resolveLayout(pt);
|
||||
|
||||
// TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`.
|
||||
if (zir_decl.kind == .@"usingnamespace") {
|
||||
if (nav_ty.toIntern() != .type_type) {
|
||||
return sema.fail(&block, ty_src, "expected type, found {}", .{nav_ty.fmt(pt)});
|
||||
}
|
||||
if (nav_val.toType().getNamespace(zcu) == .none) {
|
||||
return sema.fail(&block, ty_src, "type {} has no namespace", .{nav_val.toType().fmt(pt)});
|
||||
}
|
||||
ip.resolveNavValue(nav_id, .{
|
||||
.val = nav_val.toIntern(),
|
||||
.is_const = is_const,
|
||||
.alignment = .none,
|
||||
.@"linksection" = .none,
|
||||
.@"addrspace" = .generic,
|
||||
});
|
||||
// TODO: usingnamespace cannot participate in incremental compilation
|
||||
assert(zcu.analysis_in_progress.swapRemove(anal_unit));
|
||||
return .{ .val_changed = true };
|
||||
}
|
||||
|
||||
const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) {
|
||||
.func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen
|
||||
.variable => |v| .{ v.owner_nav == nav_id, false },
|
||||
@ -1464,7 +1443,6 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
|
||||
defer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
|
||||
|
||||
const zir_decl = zir.getDeclaration(inst_resolved.inst);
|
||||
assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
|
||||
const type_body = zir_decl.type_body.?;
|
||||
|
||||
var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
|
||||
@ -1527,7 +1505,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
|
||||
|
||||
const is_const = switch (zir_decl.kind) {
|
||||
.@"comptime" => unreachable,
|
||||
.unnamed_test, .@"test", .decltest, .@"usingnamespace", .@"const" => true,
|
||||
.unnamed_test, .@"test", .decltest, .@"const" => true,
|
||||
.@"var" => false,
|
||||
};
|
||||
|
||||
@ -2541,7 +2519,6 @@ pub fn scanNamespace(
|
||||
|
||||
try existing_by_inst.ensureTotalCapacity(gpa, @intCast(
|
||||
namespace.pub_decls.count() + namespace.priv_decls.count() +
|
||||
namespace.pub_usingnamespace.items.len + namespace.priv_usingnamespace.items.len +
|
||||
namespace.comptime_decls.items.len +
|
||||
namespace.test_decls.items.len,
|
||||
));
|
||||
@ -2554,14 +2531,6 @@ pub fn scanNamespace(
|
||||
const zir_index = ip.getNav(nav).analysis.?.zir_index;
|
||||
existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
|
||||
}
|
||||
for (namespace.pub_usingnamespace.items) |nav| {
|
||||
const zir_index = ip.getNav(nav).analysis.?.zir_index;
|
||||
existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
|
||||
}
|
||||
for (namespace.priv_usingnamespace.items) |nav| {
|
||||
const zir_index = ip.getNav(nav).analysis.?.zir_index;
|
||||
existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
|
||||
}
|
||||
for (namespace.comptime_decls.items) |cu| {
|
||||
const zir_index = ip.getComptimeUnit(cu).zir_index;
|
||||
existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .@"comptime" = cu }));
|
||||
@ -2578,8 +2547,6 @@ pub fn scanNamespace(
|
||||
|
||||
namespace.pub_decls.clearRetainingCapacity();
|
||||
namespace.priv_decls.clearRetainingCapacity();
|
||||
namespace.pub_usingnamespace.clearRetainingCapacity();
|
||||
namespace.priv_usingnamespace.clearRetainingCapacity();
|
||||
namespace.comptime_decls.clearRetainingCapacity();
|
||||
namespace.test_decls.clearRetainingCapacity();
|
||||
|
||||
@ -2607,7 +2574,6 @@ const ScanDeclIter = struct {
|
||||
/// Decl scanning is run in two passes, so that we can detect when a generated
|
||||
/// name would clash with an explicit name and use a different one.
|
||||
pass: enum { named, unnamed },
|
||||
usingnamespace_index: usize = 0,
|
||||
unnamed_test_index: usize = 0,
|
||||
|
||||
fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString {
|
||||
@ -2646,12 +2612,6 @@ const ScanDeclIter = struct {
|
||||
if (iter.pass != .unnamed) return;
|
||||
break :name .none;
|
||||
},
|
||||
.@"usingnamespace" => name: {
|
||||
if (iter.pass != .unnamed) return;
|
||||
const i = iter.usingnamespace_index;
|
||||
iter.usingnamespace_index += 1;
|
||||
break :name (try iter.avoidNameConflict("usingnamespace_{d}", .{i})).toOptional();
|
||||
},
|
||||
.unnamed_test => name: {
|
||||
if (iter.pass != .unnamed) return;
|
||||
const i = iter.unnamed_test_index;
|
||||
@ -2710,7 +2670,7 @@ const ScanDeclIter = struct {
|
||||
const name = maybe_name.unwrap().?;
|
||||
const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name);
|
||||
const nav = if (existing_unit) |eu| eu.unwrap().nav_val else nav: {
|
||||
const nav = try ip.createDeclNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index, decl.kind == .@"usingnamespace");
|
||||
const nav = try ip.createDeclNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index);
|
||||
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav);
|
||||
break :nav nav;
|
||||
};
|
||||
@ -2722,17 +2682,6 @@ const ScanDeclIter = struct {
|
||||
|
||||
const want_analysis = switch (decl.kind) {
|
||||
.@"comptime" => unreachable,
|
||||
.@"usingnamespace" => a: {
|
||||
if (comp.incremental) {
|
||||
@panic("'usingnamespace' is not supported by incremental compilation");
|
||||
}
|
||||
if (decl.is_pub) {
|
||||
try namespace.pub_usingnamespace.append(gpa, nav);
|
||||
} else {
|
||||
try namespace.priv_usingnamespace.append(gpa, nav);
|
||||
}
|
||||
break :a true;
|
||||
},
|
||||
.unnamed_test, .@"test", .decltest => a: {
|
||||
const is_named = decl.kind != .unnamed_test;
|
||||
try namespace.test_decls.append(gpa, nav);
|
||||
|
||||
@ -2758,7 +2758,7 @@ pub const Object = struct {
|
||||
llvm_arg_i += 1;
|
||||
}
|
||||
|
||||
if (fn_info.cc == .@"async") {
|
||||
if (fn_info.cc == .async) {
|
||||
@panic("TODO: LLVM backend lower async function");
|
||||
}
|
||||
|
||||
@ -2910,7 +2910,7 @@ pub const Object = struct {
|
||||
try attributes.addFnAttr(.nounwind, &o.builder);
|
||||
if (owner_mod.unwind_tables != .none) {
|
||||
try attributes.addFnAttr(
|
||||
.{ .uwtable = if (owner_mod.unwind_tables == .@"async") .@"async" else .sync },
|
||||
.{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync },
|
||||
&o.builder,
|
||||
);
|
||||
}
|
||||
@ -5273,7 +5273,7 @@ pub const FuncGen = struct {
|
||||
switch (modifier) {
|
||||
.auto, .always_tail => {},
|
||||
.never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),
|
||||
.async_kw, .no_async, .always_inline, .compile_time => unreachable,
|
||||
.no_suspend, .always_inline, .compile_time => unreachable,
|
||||
}
|
||||
|
||||
const ret_ptr = if (!sret) null else blk: {
|
||||
@ -5488,7 +5488,7 @@ pub const FuncGen = struct {
|
||||
.auto, .never_inline => .normal,
|
||||
.never_tail => .notail,
|
||||
.always_tail => .musttail,
|
||||
.async_kw, .no_async, .always_inline, .compile_time => unreachable,
|
||||
.no_suspend, .always_inline, .compile_time => unreachable,
|
||||
},
|
||||
toLlvmCallConvTag(fn_info.cc, target).?,
|
||||
try attributes.finish(&o.builder),
|
||||
@ -11861,7 +11861,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s
|
||||
}
|
||||
return switch (cc_tag) {
|
||||
.@"inline" => unreachable,
|
||||
.auto, .@"async" => .fastcc,
|
||||
.auto, .async => .fastcc,
|
||||
.naked => .ccc,
|
||||
.x86_64_sysv => .x86_64_sysvcc,
|
||||
.x86_64_win => .win64cc,
|
||||
@ -12369,7 +12369,7 @@ const ParamTypeIterator = struct {
|
||||
return .byval;
|
||||
}
|
||||
},
|
||||
.@"async" => {
|
||||
.async => {
|
||||
@panic("TODO implement async function lowering in the LLVM backend");
|
||||
},
|
||||
.x86_64_sysv => return it.nextSystemV(ty),
|
||||
@ -12624,7 +12624,7 @@ fn ccAbiPromoteInt(
|
||||
) ?std.builtin.Signedness {
|
||||
const target = zcu.getTarget();
|
||||
switch (cc) {
|
||||
.auto, .@"inline", .@"async" => return null,
|
||||
.auto, .@"inline", .async => return null,
|
||||
else => {},
|
||||
}
|
||||
const int_info = switch (ty.zigTypeTag(zcu)) {
|
||||
|
||||
@ -325,7 +325,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
|
||||
// See the `-fno-exceptions` logic for WASI.
|
||||
// The old 32-bit x86 variant of SEH doesn't use tables.
|
||||
const unwind_tables: std.builtin.UnwindTables =
|
||||
if (target.os.tag == .wasi or (target.cpu.arch == .x86 and target.os.tag == .windows)) .none else .@"async";
|
||||
if (target.os.tag == .wasi or (target.cpu.arch == .x86 and target.os.tag == .windows)) .none else .async;
|
||||
|
||||
const config = Compilation.Config.resolve(.{
|
||||
.output_mode = output_mode,
|
||||
|
||||
@ -48,7 +48,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
const optimize_mode = comp.compilerRtOptMode();
|
||||
const strip = comp.compilerRtStrip();
|
||||
const unwind_tables: std.builtin.UnwindTables =
|
||||
if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async";
|
||||
if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .async;
|
||||
const link_libcpp = target.os.tag.isDarwin();
|
||||
|
||||
const config = Compilation.Config.resolve(.{
|
||||
|
||||
@ -29,7 +29,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
|
||||
const output_mode = .Lib;
|
||||
const target = &comp.root_mod.resolved_target.result;
|
||||
const unwind_tables: std.builtin.UnwindTables =
|
||||
if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async";
|
||||
if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .async;
|
||||
const config = Compilation.Config.resolve(.{
|
||||
.output_mode = output_mode,
|
||||
.resolved_target = comp.root_mod.resolved_target,
|
||||
|
||||
@ -29,7 +29,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
|
||||
const target = comp.getTarget();
|
||||
|
||||
// The old 32-bit x86 variant of SEH doesn't use tables.
|
||||
const unwind_tables: std.builtin.UnwindTables = if (target.cpu.arch != .x86) .@"async" else .none;
|
||||
const unwind_tables: std.builtin.UnwindTables = if (target.cpu.arch != .x86) .async else .none;
|
||||
|
||||
switch (crt_file) {
|
||||
.crt2_o => {
|
||||
|
||||
@ -2489,7 +2489,7 @@ fn initWipNavInner(
|
||||
const addr: Loc = .{ .addr_reloc = sym_index };
|
||||
const loc: Loc = if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr;
|
||||
switch (decl.kind) {
|
||||
.unnamed_test, .@"test", .decltest, .@"comptime", .@"usingnamespace" => unreachable,
|
||||
.unnamed_test, .@"test", .decltest, .@"comptime" => unreachable,
|
||||
.@"const" => {
|
||||
const const_ty_reloc_index = try wip_nav.refForward();
|
||||
try wip_nav.infoExprLoc(loc);
|
||||
@ -2775,7 +2775,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
|
||||
|
||||
const is_test = switch (decl.kind) {
|
||||
.unnamed_test, .@"test", .decltest => true,
|
||||
.@"comptime", .@"usingnamespace", .@"const", .@"var" => false,
|
||||
.@"comptime", .@"const", .@"var" => false,
|
||||
};
|
||||
if (is_test) {
|
||||
// This isn't actually a comptime Nav! It's a test, so it'll definitely never be referenced at comptime.
|
||||
@ -3596,7 +3596,7 @@ fn updateLazyType(
|
||||
// For better or worse, we try to match what Clang emits.
|
||||
break :cc switch (func_type.cc) {
|
||||
.@"inline" => .nocall,
|
||||
.@"async", .auto, .naked => .normal,
|
||||
.async, .auto, .naked => .normal,
|
||||
.x86_64_sysv => .LLVM_X86_64SysV,
|
||||
.x86_64_win => .LLVM_Win64,
|
||||
.x86_64_regcall_v3_sysv => .LLVM_X86RegCall,
|
||||
|
||||
12
src/main.zig
12
src/main.zig
@ -1416,7 +1416,7 @@ fn buildOutputType(
|
||||
} else if (mem.eql(u8, arg, "-funwind-tables")) {
|
||||
mod_opts.unwind_tables = .sync;
|
||||
} else if (mem.eql(u8, arg, "-fasync-unwind-tables")) {
|
||||
mod_opts.unwind_tables = .@"async";
|
||||
mod_opts.unwind_tables = .async;
|
||||
} else if (mem.eql(u8, arg, "-fno-unwind-tables")) {
|
||||
mod_opts.unwind_tables = .none;
|
||||
} else if (mem.eql(u8, arg, "-fstack-check")) {
|
||||
@ -2035,15 +2035,15 @@ fn buildOutputType(
|
||||
.none => {
|
||||
mod_opts.unwind_tables = .sync;
|
||||
},
|
||||
.sync, .@"async" => {},
|
||||
.sync, .async => {},
|
||||
} else {
|
||||
mod_opts.unwind_tables = .sync;
|
||||
},
|
||||
.no_unwind_tables => mod_opts.unwind_tables = .none,
|
||||
.asynchronous_unwind_tables => mod_opts.unwind_tables = .@"async",
|
||||
.asynchronous_unwind_tables => mod_opts.unwind_tables = .async,
|
||||
.no_asynchronous_unwind_tables => if (mod_opts.unwind_tables) |uwt| switch (uwt) {
|
||||
.none, .sync => {},
|
||||
.@"async" => {
|
||||
.async => {
|
||||
mod_opts.unwind_tables = .sync;
|
||||
},
|
||||
} else {
|
||||
@ -2951,7 +2951,7 @@ fn buildOutputType(
|
||||
create_module.opts.any_fuzz = true;
|
||||
if (mod_opts.unwind_tables) |uwt| switch (uwt) {
|
||||
.none => {},
|
||||
.sync, .@"async" => create_module.opts.any_unwind_tables = true,
|
||||
.sync, .async => create_module.opts.any_unwind_tables = true,
|
||||
};
|
||||
if (mod_opts.strip == false)
|
||||
create_module.opts.any_non_stripped = true;
|
||||
@ -7413,7 +7413,7 @@ fn handleModArg(
|
||||
create_module.opts.any_fuzz = true;
|
||||
if (mod_opts.unwind_tables) |uwt| switch (uwt) {
|
||||
.none => {},
|
||||
.sync, .@"async" => create_module.opts.any_unwind_tables = true,
|
||||
.sync, .async => create_module.opts.any_unwind_tables = true,
|
||||
};
|
||||
if (mod_opts.strip == false)
|
||||
create_module.opts.any_non_stripped = true;
|
||||
|
||||
@ -261,14 +261,12 @@ const Writer = struct {
|
||||
.tag_name,
|
||||
.type_name,
|
||||
.frame_type,
|
||||
.frame_size,
|
||||
.clz,
|
||||
.ctz,
|
||||
.pop_count,
|
||||
.byte_swap,
|
||||
.bit_reverse,
|
||||
.@"resume",
|
||||
.@"await",
|
||||
.make_ptr_const,
|
||||
.validate_deref,
|
||||
.validate_const,
|
||||
@ -565,7 +563,6 @@ const Writer = struct {
|
||||
|
||||
.tuple_decl => try self.writeTupleDecl(stream, extended),
|
||||
|
||||
.await_nosuspend,
|
||||
.c_undef,
|
||||
.c_include,
|
||||
.set_float_mode,
|
||||
@ -611,7 +608,6 @@ const Writer = struct {
|
||||
try self.writeSrcNode(stream, inst_data.node);
|
||||
},
|
||||
|
||||
.builtin_async_call => try self.writeBuiltinAsyncCall(stream, extended),
|
||||
.cmpxchg => try self.writeCmpxchg(stream, extended),
|
||||
.ptr_cast_full => try self.writePtrCastFull(stream, extended),
|
||||
.ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
|
||||
@ -932,19 +928,6 @@ const Writer = struct {
|
||||
try self.writeSrcNode(stream, extra.src_node);
|
||||
}
|
||||
|
||||
fn writeBuiltinAsyncCall(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
|
||||
const extra = self.code.extraData(Zir.Inst.AsyncCall, extended.operand).data;
|
||||
try self.writeInstRef(stream, extra.frame_buffer);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.result_ptr);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.fn_ptr);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.args);
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrcNode(stream, extra.node);
|
||||
}
|
||||
|
||||
fn writeParam(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok;
|
||||
const extra = self.code.extraData(Zir.Inst.Param, inst_data.payload_index);
|
||||
@ -2605,7 +2588,6 @@ const Writer = struct {
|
||||
}
|
||||
switch (decl.kind) {
|
||||
.@"comptime" => try stream.writeAll("comptime"),
|
||||
.@"usingnamespace" => try stream.writeAll("usingnamespace"),
|
||||
.unnamed_test => try stream.writeAll("test"),
|
||||
.@"test", .decltest, .@"const", .@"var" => {
|
||||
try stream.print("{s} '{s}'", .{ @tagName(decl.kind), self.code.nullTerminatedString(decl.name) });
|
||||
|
||||
@ -483,12 +483,12 @@ pub fn clangSupportsNoImplicitFloatArg(target: *const std.Target) bool {
|
||||
pub fn defaultUnwindTables(target: *const std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables {
|
||||
if (target.os.tag == .windows) {
|
||||
// The old 32-bit x86 variant of SEH doesn't use tables.
|
||||
return if (target.cpu.arch != .x86) .@"async" else .none;
|
||||
return if (target.cpu.arch != .x86) .async else .none;
|
||||
}
|
||||
if (target.os.tag.isDarwin()) return .@"async";
|
||||
if (libunwind) return .@"async";
|
||||
if (libtsan) return .@"async";
|
||||
if (std.debug.Dwarf.abi.supportsUnwinding(target)) return .@"async";
|
||||
if (target.os.tag.isDarwin()) return .async;
|
||||
if (libunwind) return .async;
|
||||
if (libtsan) return .async;
|
||||
if (std.debug.Dwarf.abi.supportsUnwinding(target)) return .async;
|
||||
return .none;
|
||||
}
|
||||
|
||||
@ -815,7 +815,7 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
|
||||
|
||||
pub fn fnCallConvAllowsZigTypes(cc: std.builtin.CallingConvention) bool {
|
||||
return switch (cc) {
|
||||
.auto, .@"async", .@"inline" => true,
|
||||
.auto, .async, .@"inline" => true,
|
||||
// For now we want to authorize PTX kernel to use zig objects, even if
|
||||
// we end up exposing the ABI. The goal is to experiment with more
|
||||
// integrated CPU/GPU code.
|
||||
|
||||
BIN
stage1/zig1.wasm
BIN
stage1/zig1.wasm
Binary file not shown.
@ -5,9 +5,7 @@ test {
|
||||
_ = @import("behavior/align.zig");
|
||||
_ = @import("behavior/alignof.zig");
|
||||
_ = @import("behavior/array.zig");
|
||||
_ = @import("behavior/async_fn.zig");
|
||||
_ = @import("behavior/atomics.zig");
|
||||
_ = @import("behavior/await_struct.zig");
|
||||
_ = @import("behavior/basic.zig");
|
||||
_ = @import("behavior/bit_shifting.zig");
|
||||
_ = @import("behavior/bitcast.zig");
|
||||
@ -103,7 +101,6 @@ test {
|
||||
_ = @import("behavior/underscore.zig");
|
||||
_ = @import("behavior/union.zig");
|
||||
_ = @import("behavior/union_with_members.zig");
|
||||
_ = @import("behavior/usingnamespace.zig");
|
||||
_ = @import("behavior/var_args.zig");
|
||||
// https://github.com/llvm/llvm-project/issues/118879
|
||||
// https://github.com/llvm/llvm-project/issues/134659
|
||||
|
||||
@ -425,30 +425,6 @@ test "struct field explicit alignment" {
|
||||
try expect(@intFromPtr(&node.massive_byte) % 64 == 0);
|
||||
}
|
||||
|
||||
test "align(@alignOf(T)) T does not force resolution of T" {
|
||||
if (true) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
const A = struct {
|
||||
a: *align(@alignOf(A)) A,
|
||||
};
|
||||
fn doTheTest() void {
|
||||
suspend {
|
||||
resume @frame();
|
||||
}
|
||||
_ = bar(@Frame(doTheTest));
|
||||
}
|
||||
fn bar(comptime T: type) *align(@alignOf(T)) T {
|
||||
ok = true;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var ok = false;
|
||||
};
|
||||
_ = async S.doTheTest();
|
||||
try expect(S.ok);
|
||||
}
|
||||
|
||||
test "align(N) on functions" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,47 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
const Foo = struct {
|
||||
x: i32,
|
||||
};
|
||||
|
||||
var await_a_promise: anyframe = undefined;
|
||||
var await_final_result = Foo{ .x = 0 };
|
||||
|
||||
test "coroutine await struct" {
|
||||
if (true) return error.SkipZigTest; // TODO
|
||||
|
||||
await_seq('a');
|
||||
var p = async await_amain();
|
||||
_ = &p;
|
||||
await_seq('f');
|
||||
resume await_a_promise;
|
||||
await_seq('i');
|
||||
try expect(await_final_result.x == 1234);
|
||||
try expect(std.mem.eql(u8, &await_points, "abcdefghi"));
|
||||
}
|
||||
fn await_amain() callconv(.@"async") void {
|
||||
await_seq('b');
|
||||
var p = async await_another();
|
||||
await_seq('e');
|
||||
await_final_result = await p;
|
||||
await_seq('h');
|
||||
}
|
||||
fn await_another() callconv(.@"async") Foo {
|
||||
await_seq('c');
|
||||
suspend {
|
||||
await_seq('d');
|
||||
await_a_promise = @frame();
|
||||
}
|
||||
await_seq('g');
|
||||
return Foo{ .x = 1234 };
|
||||
}
|
||||
|
||||
var await_points = [_]u8{0} ** "abcdefghi".len;
|
||||
var await_seq_index: usize = 0;
|
||||
|
||||
fn await_seq(c: u8) void {
|
||||
await_points[await_seq_index] = c;
|
||||
await_seq_index += 1;
|
||||
}
|
||||
@ -1107,27 +1107,6 @@ test "inline call of function with a switch inside the return statement" {
|
||||
try expect(S.foo(1) == 1);
|
||||
}
|
||||
|
||||
test "ambiguous reference error ignores current declaration" {
|
||||
const S = struct {
|
||||
const foo = 666;
|
||||
|
||||
const a = @This();
|
||||
const b = struct {
|
||||
const foo = a.foo;
|
||||
const bar = struct {
|
||||
bar: u32 = b.foo,
|
||||
};
|
||||
|
||||
comptime {
|
||||
_ = b.foo;
|
||||
}
|
||||
};
|
||||
|
||||
usingnamespace b;
|
||||
};
|
||||
try expect(S.b.foo == 666);
|
||||
}
|
||||
|
||||
test "pointer to zero sized global is mutable" {
|
||||
const S = struct {
|
||||
const Thing = struct {};
|
||||
|
||||
@ -37,7 +37,7 @@ test "basic invocations" {
|
||||
comptime {
|
||||
// comptime calls with supported modifiers
|
||||
try expect(@call(.auto, foo, .{2}) == 1234);
|
||||
try expect(@call(.no_async, foo, .{3}) == 1234);
|
||||
try expect(@call(.no_suspend, foo, .{3}) == 1234);
|
||||
try expect(@call(.always_tail, foo, .{4}) == 1234);
|
||||
try expect(@call(.always_inline, foo, .{5}) == 1234);
|
||||
}
|
||||
@ -45,7 +45,7 @@ test "basic invocations" {
|
||||
const result = @call(.compile_time, foo, .{6}) == 1234;
|
||||
comptime assert(result);
|
||||
// runtime calls of comptime-known function
|
||||
try expect(@call(.no_async, foo, .{7}) == 1234);
|
||||
try expect(@call(.no_suspend, foo, .{7}) == 1234);
|
||||
try expect(@call(.never_tail, foo, .{8}) == 1234);
|
||||
try expect(@call(.never_inline, foo, .{9}) == 1234);
|
||||
// CBE does not support attributes on runtime functions
|
||||
@ -53,7 +53,7 @@ test "basic invocations" {
|
||||
// runtime calls of non comptime-known function
|
||||
var alias_foo = &foo;
|
||||
_ = &alias_foo;
|
||||
try expect(@call(.no_async, alias_foo, .{10}) == 1234);
|
||||
try expect(@call(.no_suspend, alias_foo, .{10}) == 1234);
|
||||
try expect(@call(.never_tail, alias_foo, .{11}) == 1234);
|
||||
try expect(@call(.never_inline, alias_foo, .{12}) == 1234);
|
||||
}
|
||||
@ -507,29 +507,6 @@ test "call inline fn through pointer" {
|
||||
try f(123);
|
||||
}
|
||||
|
||||
test "call coerced function" {
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
||||
const T = struct {
|
||||
x: f64,
|
||||
const T = @This();
|
||||
usingnamespace Implement(1);
|
||||
const F = fn (comptime f64) type;
|
||||
const Implement: F = opaque {
|
||||
fn implementer(comptime val: anytype) type {
|
||||
return opaque {
|
||||
fn incr(self: T) T {
|
||||
return .{ .x = self.x + val };
|
||||
}
|
||||
};
|
||||
}
|
||||
}.implementer;
|
||||
};
|
||||
|
||||
const a = T{ .x = 3 };
|
||||
try std.testing.expect(a.incr().x == 4);
|
||||
}
|
||||
|
||||
test "call function in comptime field" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
|
||||
|
||||
@ -18,16 +18,6 @@ test "importing the same thing gives the same import" {
|
||||
try expect(@import("std") == @import("std"));
|
||||
}
|
||||
|
||||
test "import in non-toplevel scope" {
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
usingnamespace @import("import/a_namespace.zig");
|
||||
};
|
||||
try expect(@as(i32, 1234) == S.foo());
|
||||
}
|
||||
|
||||
test "import empty file" {
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
||||
@ -236,17 +236,6 @@ test "call method with mutable reference to struct with no fields" {
|
||||
try expect(s.do());
|
||||
}
|
||||
|
||||
test "usingnamespace within struct scope" {
|
||||
const S = struct {
|
||||
usingnamespace struct {
|
||||
pub fn inner() i32 {
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
};
|
||||
try expect(@as(i32, 42) == S.inner());
|
||||
}
|
||||
|
||||
test "struct field init with catch" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
@ -592,24 +592,6 @@ test "StructField.is_comptime" {
|
||||
try expect(info.fields[1].is_comptime);
|
||||
}
|
||||
|
||||
test "typeInfo resolves usingnamespace declarations" {
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
const A = struct {
|
||||
pub const f1 = 42;
|
||||
};
|
||||
|
||||
const B = struct {
|
||||
pub const f0 = 42;
|
||||
pub usingnamespace A;
|
||||
};
|
||||
|
||||
const decls = @typeInfo(B).@"struct".decls;
|
||||
try expect(decls.len == 2);
|
||||
try expectEqualStrings(decls[0].name, "f0");
|
||||
try expectEqualStrings(decls[1].name, "f1");
|
||||
}
|
||||
|
||||
test "value from struct @typeInfo default_value_ptr can be loaded at comptime" {
|
||||
comptime {
|
||||
const a = @typeInfo(@TypeOf(.{ .foo = @as(u8, 1) })).@"struct".fields[0].default_value_ptr;
|
||||
@ -617,77 +599,12 @@ test "value from struct @typeInfo default_value_ptr can be loaded at comptime" {
|
||||
}
|
||||
}
|
||||
|
||||
test "@typeInfo decls and usingnamespace" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
const A = struct {
|
||||
pub const x = 5;
|
||||
pub const y = 34;
|
||||
|
||||
comptime {}
|
||||
};
|
||||
const B = struct {
|
||||
pub usingnamespace A;
|
||||
pub const z = 56;
|
||||
|
||||
test {}
|
||||
};
|
||||
const decls = @typeInfo(B).@"struct".decls;
|
||||
try expect(decls.len == 3);
|
||||
try expectEqualStrings(decls[0].name, "z");
|
||||
try expectEqualStrings(decls[1].name, "x");
|
||||
try expectEqualStrings(decls[2].name, "y");
|
||||
}
|
||||
|
||||
test "@typeInfo decls ignore dependency loops" {
|
||||
const S = struct {
|
||||
pub fn Def(comptime T: type) type {
|
||||
std.debug.assert(@typeInfo(T).@"struct".decls.len == 1);
|
||||
return struct {
|
||||
const foo = u32;
|
||||
};
|
||||
}
|
||||
usingnamespace Def(@This());
|
||||
};
|
||||
_ = S.foo;
|
||||
}
|
||||
|
||||
test "type info of tuple of string literal default value" {
|
||||
const struct_field = @typeInfo(@TypeOf(.{"hi"})).@"struct".fields[0];
|
||||
const value = struct_field.defaultValue().?;
|
||||
comptime std.debug.assert(value[0] == 'h');
|
||||
}
|
||||
|
||||
test "@typeInfo only contains pub decls" {
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
const other = struct {
|
||||
const std = @import("std");
|
||||
|
||||
usingnamespace struct {
|
||||
pub const inside_non_pub_usingnamespace = 0;
|
||||
};
|
||||
|
||||
pub const Enum = enum {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
};
|
||||
|
||||
pub const Struct = struct {
|
||||
foo: i32,
|
||||
};
|
||||
};
|
||||
const ti = @typeInfo(other);
|
||||
const decls = ti.@"struct".decls;
|
||||
|
||||
try std.testing.expectEqual(2, decls.len);
|
||||
try std.testing.expectEqualStrings("Enum", decls[0].name);
|
||||
try std.testing.expectEqualStrings("Struct", decls[1].name);
|
||||
}
|
||||
|
||||
test "@typeInfo function with generic return type and inferred error set" {
|
||||
const S = struct {
|
||||
fn testFn(comptime T: type) !T {}
|
||||
|
||||
@ -1,125 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
const A = struct {
|
||||
pub const B = bool;
|
||||
};
|
||||
|
||||
const C = struct {
|
||||
usingnamespace A;
|
||||
};
|
||||
|
||||
test "basic usingnamespace" {
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
try std.testing.expect(C.B == bool);
|
||||
}
|
||||
|
||||
fn Foo(comptime T: type) type {
|
||||
return struct {
|
||||
usingnamespace T;
|
||||
};
|
||||
}
|
||||
|
||||
test "usingnamespace inside a generic struct" {
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
const std2 = Foo(std);
|
||||
const testing2 = Foo(std.testing);
|
||||
try std2.testing.expect(true);
|
||||
try testing2.expect(true);
|
||||
}
|
||||
|
||||
usingnamespace struct {
|
||||
pub const foo = 42;
|
||||
};
|
||||
|
||||
test "usingnamespace does not redeclare an imported variable" {
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
try comptime std.testing.expect(@This().foo == 42);
|
||||
}
|
||||
|
||||
usingnamespace @import("usingnamespace/foo.zig");
|
||||
test "usingnamespace omits mixing in private functions" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
try expect(@This().privateFunction());
|
||||
try expect(!@This().printText());
|
||||
}
|
||||
fn privateFunction() bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
test {
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
_ = @import("usingnamespace/import_segregation.zig");
|
||||
}
|
||||
|
||||
usingnamespace @import("usingnamespace/a.zig");
|
||||
test "two files usingnamespace import each other" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
try expect(@This().ok());
|
||||
}
|
||||
|
||||
test {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
const AA = struct {
|
||||
x: i32,
|
||||
fn b(x: i32) @This() {
|
||||
return .{ .x = x };
|
||||
}
|
||||
fn c() type {
|
||||
return if (true) struct {
|
||||
const expected: i32 = 42;
|
||||
} else struct {};
|
||||
}
|
||||
usingnamespace c();
|
||||
};
|
||||
const a = AA.b(42);
|
||||
try expect(a.x == AA.c().expected);
|
||||
}
|
||||
|
||||
const Bar = struct {
|
||||
usingnamespace Mixin;
|
||||
};
|
||||
|
||||
const Mixin = struct {
|
||||
pub fn two(self: Bar) void {
|
||||
_ = self;
|
||||
}
|
||||
};
|
||||
|
||||
test "container member access usingnamespace decls" {
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
var foo = Bar{};
|
||||
foo.two();
|
||||
}
|
||||
|
||||
usingnamespace opaque {};
|
||||
|
||||
usingnamespace @Type(.{ .@"struct" = .{
|
||||
.layout = .auto,
|
||||
.fields = &.{},
|
||||
.decls = &.{},
|
||||
.is_tuple = false,
|
||||
} });
|
||||
@ -1,7 +0,0 @@
|
||||
usingnamespace @import("b.zig");
|
||||
|
||||
pub const a_text = "OK\n";
|
||||
|
||||
pub fn ok() bool {
|
||||
return @import("std").mem.eql(u8, @This().b_text, "OK\n");
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
usingnamespace @import("a.zig");
|
||||
|
||||
pub const b_text = @This().a_text;
|
||||
@ -1,8 +0,0 @@
|
||||
usingnamespace @import("other.zig");
|
||||
|
||||
pub var saw_bar_function = false;
|
||||
pub fn bar_function() void {
|
||||
if (@This().foo_function()) {
|
||||
saw_bar_function = true;
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
// purposefully conflicting function with main source file
|
||||
// but it's private so it should be OK
|
||||
fn privateFunction() bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn printText() bool {
|
||||
return privateFunction();
|
||||
}
|
||||
|
||||
pub var saw_foo_function = false;
|
||||
pub fn foo_function() void {
|
||||
saw_foo_function = true;
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
const expect = @import("std").testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
usingnamespace @import("foo.zig");
|
||||
usingnamespace @import("bar.zig");
|
||||
|
||||
test "no clobbering happened" {
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
||||
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
|
||||
// https://github.com/ziglang/zig/issues/16846
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
|
||||
@This().foo_function();
|
||||
@This().bar_function();
|
||||
try expect(@This().saw_foo_function);
|
||||
try expect(@This().saw_bar_function);
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
pub fn foo_function() bool {
|
||||
// this one conflicts with the one from foo
|
||||
return true;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
export fn entry() void {
|
||||
_ = async amain();
|
||||
}
|
||||
fn amain() callconv(.@"async") void {
|
||||
var x: [@sizeOf(@Frame(amain))]u8 = undefined;
|
||||
_ = &x;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:4:1: error: cannot resolve '@Frame(amain)': function not fully analyzed yet
|
||||
@ -1,17 +0,0 @@
|
||||
export fn entry() void {
|
||||
_ = async amain();
|
||||
}
|
||||
fn amain() callconv(.@"async") void {
|
||||
other();
|
||||
}
|
||||
fn other() void {
|
||||
var x: [@sizeOf(@Frame(amain))]u8 = undefined;
|
||||
_ = &x;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:4:1: error: unable to determine async function frame of 'amain'
|
||||
// tmp.zig:5:10: note: analysis of function 'other' depends on the frame
|
||||
@ -1,19 +0,0 @@
|
||||
export fn a() void {
|
||||
const f = async func();
|
||||
resume f;
|
||||
}
|
||||
export fn b() void {
|
||||
const f = async func();
|
||||
var x: anyframe = &f;
|
||||
_ = &x;
|
||||
}
|
||||
fn func() void {
|
||||
suspend {}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:12: error: expected type 'anyframe', found '*const @Frame(func)'
|
||||
// tmp.zig:7:24: error: expected type 'anyframe', found '*const @Frame(func)'
|
||||
@ -1,18 +0,0 @@
|
||||
export fn entry() void {
|
||||
foo();
|
||||
}
|
||||
fn foo() void {
|
||||
bar();
|
||||
}
|
||||
fn bar() void {
|
||||
suspend {}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:1: error: function with calling convention 'C' cannot be async
|
||||
// tmp.zig:2:8: note: async function call here
|
||||
// tmp.zig:5:8: note: async function call here
|
||||
// tmp.zig:8:5: note: suspends here
|
||||
@ -1,36 +0,0 @@
|
||||
var frame: ?anyframe = null;
|
||||
|
||||
export fn a() void {
|
||||
_ = async rangeSum(10);
|
||||
while (frame) |f| resume f;
|
||||
}
|
||||
|
||||
fn rangeSum(x: i32) i32 {
|
||||
suspend {
|
||||
frame = @frame();
|
||||
}
|
||||
frame = null;
|
||||
|
||||
if (x == 0) return 0;
|
||||
const child = rangeSumIndirect(x - 1);
|
||||
return child + 1;
|
||||
}
|
||||
|
||||
fn rangeSumIndirect(x: i32) i32 {
|
||||
suspend {
|
||||
frame = @frame();
|
||||
}
|
||||
frame = null;
|
||||
|
||||
if (x == 0) return 0;
|
||||
const child = rangeSum(x - 1);
|
||||
return child + 1;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:8:1: error: '@Frame(rangeSum)' depends on itself
|
||||
// tmp.zig:15:35: note: when analyzing type '@Frame(rangeSum)' here
|
||||
// tmp.zig:28:25: note: when analyzing type '@Frame(rangeSumIndirect)' here
|
||||
@ -1,15 +0,0 @@
|
||||
export fn entry() void {
|
||||
var frame = async func();
|
||||
var result = await frame;
|
||||
_ = &result;
|
||||
}
|
||||
fn func() void {
|
||||
suspend {}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:1:1: error: function with calling convention 'C' cannot be async
|
||||
// tmp.zig:3:18: note: await here is a suspend point
|
||||
@ -1,12 +0,0 @@
|
||||
export fn entry() void {
|
||||
_ = async amain();
|
||||
}
|
||||
fn amain() callconv(.@"async") void {
|
||||
return error.ShouldBeCompileError;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:17: error: expected type 'void', found 'error{ShouldBeCompileError}'
|
||||
@ -1,15 +0,0 @@
|
||||
export fn entry() void {
|
||||
_ = async amain();
|
||||
}
|
||||
fn amain() void {
|
||||
var ptr = afunc;
|
||||
_ = ptr();
|
||||
_ = &ptr;
|
||||
}
|
||||
fn afunc() callconv(.@"async") void {}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:12: error: function is not comptime-known; @asyncCall required
|
||||
@ -1,13 +0,0 @@
|
||||
export fn entry() void {
|
||||
var ptr = afunc;
|
||||
_ = async ptr();
|
||||
_ = &ptr;
|
||||
}
|
||||
|
||||
fn afunc() callconv(.@"async") void {}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:15: error: function is not comptime-known; @asyncCall required
|
||||
@ -1,16 +0,0 @@
|
||||
export fn entry() void {
|
||||
var frame: @Frame(foo) = undefined;
|
||||
frame = async bar();
|
||||
}
|
||||
fn foo() void {
|
||||
suspend {}
|
||||
}
|
||||
fn bar() void {
|
||||
suspend {}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:13: error: expected type '*@Frame(bar)', found '*@Frame(foo)'
|
||||
@ -1,16 +0,0 @@
|
||||
export fn entry() void {
|
||||
_ = async amain();
|
||||
}
|
||||
fn amain() i32 {
|
||||
var frame: @Frame(foo) = undefined;
|
||||
return await @asyncCall(&frame, false, foo, .{});
|
||||
}
|
||||
fn foo() i32 {
|
||||
return 1234;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:6:37: error: expected type '*i32', found 'bool'
|
||||
@ -1,31 +0,0 @@
|
||||
//! The full test name would be:
|
||||
//! struct field type resolution marks transitive error from bad usingnamespace in @typeInfo call from non-initial field type
|
||||
//!
|
||||
//! This test is rather esoteric. It's ensuring that errors triggered by `@typeInfo` analyzing
|
||||
//! a bad `usingnamespace` correctly trigger transitive errors when analyzed by struct field type
|
||||
//! resolution, meaning we don't incorrectly analyze code past the uses of `S`.
|
||||
|
||||
const S = struct {
|
||||
ok: u32,
|
||||
bad: @typeInfo(T),
|
||||
};
|
||||
|
||||
const T = struct {
|
||||
pub usingnamespace @compileError("usingnamespace analyzed");
|
||||
};
|
||||
|
||||
comptime {
|
||||
const a: S = .{ .ok = 123, .bad = undefined };
|
||||
_ = a;
|
||||
@compileError("should not be reached");
|
||||
}
|
||||
|
||||
comptime {
|
||||
const b: S = .{ .ok = 123, .bad = undefined };
|
||||
_ = b;
|
||||
@compileError("should not be reached");
|
||||
}
|
||||
|
||||
// error
|
||||
//
|
||||
// :14:24: error: usingnamespace analyzed
|
||||
@ -1,15 +0,0 @@
|
||||
export fn entry() void {
|
||||
nosuspend {
|
||||
const bar = async foo();
|
||||
suspend {}
|
||||
resume bar;
|
||||
}
|
||||
}
|
||||
fn foo() void {}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:9: error: suspend inside nosuspend block
|
||||
// :2:5: note: nosuspend block here
|
||||
@ -1,15 +0,0 @@
|
||||
export fn entry() void {
|
||||
_ = async foo();
|
||||
}
|
||||
fn foo() void {
|
||||
suspend {
|
||||
suspend {}
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:9: error: cannot suspend inside suspend block
|
||||
// :5:5: note: other suspend block here
|
||||
@ -1,7 +0,0 @@
|
||||
usingnamespace void;
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:16: error: type void has no namespace
|
||||
@ -1,26 +0,0 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
pub fn main() !void {
|
||||
if (builtin.zig_backend == .stage1 and builtin.os.tag == .wasi) {
|
||||
// TODO file a bug for this failure
|
||||
std.process.exit(0); // skip the test
|
||||
}
|
||||
var bytes: [1]u8 align(16) = undefined;
|
||||
var ptr = other;
|
||||
_ = &ptr;
|
||||
var frame = @asyncCall(&bytes, {}, ptr, .{});
|
||||
_ = &frame;
|
||||
return error.TestFailed;
|
||||
}
|
||||
fn other() callconv(.@"async") void {
|
||||
suspend {}
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -1,29 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
var frame: anyframe = undefined;
|
||||
|
||||
pub fn main() !void {
|
||||
_ = async amain();
|
||||
resume frame;
|
||||
return error.TestFailed;
|
||||
}
|
||||
|
||||
fn amain() void {
|
||||
var f = async func();
|
||||
await f;
|
||||
await f;
|
||||
}
|
||||
|
||||
fn func() void {
|
||||
suspend {
|
||||
frame = @frame();
|
||||
}
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -1,38 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
|
||||
var failing_frame: @Frame(failing) = undefined;
|
||||
|
||||
pub fn main() !void {
|
||||
const p = nonFailing();
|
||||
resume p;
|
||||
const p2 = async printTrace(p);
|
||||
_ = p2;
|
||||
return error.TestFailed;
|
||||
}
|
||||
|
||||
fn nonFailing() anyframe->anyerror!void {
|
||||
failing_frame = async failing();
|
||||
return &failing_frame;
|
||||
}
|
||||
|
||||
fn failing() anyerror!void {
|
||||
suspend {}
|
||||
return second();
|
||||
}
|
||||
|
||||
fn second() callconv(.@"async") anyerror!void {
|
||||
return error.Fail;
|
||||
}
|
||||
|
||||
fn printTrace(p: anyframe->anyerror!void) void {
|
||||
(await p) catch unreachable;
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -1,19 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
pub fn main() !void {
|
||||
var p = async suspendOnce();
|
||||
resume p; //ok
|
||||
resume p; //bad
|
||||
return error.TestFailed;
|
||||
}
|
||||
fn suspendOnce() void {
|
||||
suspend {}
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -1,21 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
pub fn main() !void {
|
||||
var frame = async first();
|
||||
resume frame;
|
||||
return error.TestFailed;
|
||||
}
|
||||
fn first() void {
|
||||
other();
|
||||
}
|
||||
fn other() void {
|
||||
suspend {}
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -1,22 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
pub fn main() !void {
|
||||
var frame = async first();
|
||||
resume frame;
|
||||
return error.TestFailed;
|
||||
}
|
||||
fn first() void {
|
||||
var frame = async other();
|
||||
await frame;
|
||||
}
|
||||
fn other() void {
|
||||
suspend {}
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -1,32 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
fn foo() void {
|
||||
suspend {
|
||||
global_frame = @frame();
|
||||
}
|
||||
var f = async bar(@frame());
|
||||
_ = &f;
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
fn bar(frame: anyframe) void {
|
||||
suspend {
|
||||
resume frame;
|
||||
}
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
var global_frame: anyframe = undefined;
|
||||
pub fn main() !void {
|
||||
_ = async foo();
|
||||
resume global_frame;
|
||||
std.process.exit(1);
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -1,27 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
|
||||
_ = message;
|
||||
_ = stack_trace;
|
||||
std.process.exit(0);
|
||||
}
|
||||
fn foo() void {
|
||||
var f = async bar(@frame());
|
||||
_ = &f;
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
fn bar(frame: anyframe) void {
|
||||
suspend {
|
||||
resume frame;
|
||||
}
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
_ = async foo();
|
||||
return error.TestFailed;
|
||||
}
|
||||
// run
|
||||
// backend=stage1
|
||||
// target=native
|
||||
@ -48,9 +48,6 @@
|
||||
.pkg_import = .{
|
||||
.path = "pkg_import",
|
||||
},
|
||||
.use_alias = .{
|
||||
.path = "use_alias",
|
||||
},
|
||||
.install_raw_hex = .{
|
||||
.path = "install_raw_hex",
|
||||
},
|
||||
|
||||
@ -29,7 +29,7 @@ pub fn build(b: *std.Build) void {
|
||||
.root_source_file = b.path("unwind.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.unwind_tables = if (target.result.os.tag.isDarwin()) .@"async" else null,
|
||||
.unwind_tables = if (target.result.os.tag.isDarwin()) .async else null,
|
||||
.omit_frame_pointer = false,
|
||||
}),
|
||||
});
|
||||
@ -54,7 +54,7 @@ pub fn build(b: *std.Build) void {
|
||||
.root_source_file = b.path("unwind.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.unwind_tables = .@"async",
|
||||
.unwind_tables = .async,
|
||||
.omit_frame_pointer = true,
|
||||
}),
|
||||
// self-hosted lacks omit_frame_pointer support
|
||||
@ -101,7 +101,7 @@ pub fn build(b: *std.Build) void {
|
||||
.root_source_file = b.path("shared_lib_unwind.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.unwind_tables = if (target.result.os.tag.isDarwin()) .@"async" else null,
|
||||
.unwind_tables = if (target.result.os.tag.isDarwin()) .async else null,
|
||||
.omit_frame_pointer = true,
|
||||
}),
|
||||
// zig objcopy doesn't support incremental binaries
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test it");
|
||||
b.default_step = test_step;
|
||||
|
||||
const optimize: std.builtin.OptimizeMode = .Debug;
|
||||
|
||||
const main = b.addTest(.{ .root_module = b.createModule(.{
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.target = b.graph.host,
|
||||
.optimize = optimize,
|
||||
}) });
|
||||
main.root_module.addIncludePath(b.path("."));
|
||||
|
||||
test_step.dependOn(&b.addRunArtifact(main).step);
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
pub usingnamespace @cImport(@cInclude("foo.h"));
|
||||
@ -1,4 +0,0 @@
|
||||
struct Foo {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
@ -1,11 +0,0 @@
|
||||
const c = @import("c.zig");
|
||||
const expect = @import("std").testing.expect;
|
||||
|
||||
test "symbol exists" {
|
||||
var foo = c.Foo{
|
||||
.a = 1,
|
||||
.b = 1,
|
||||
};
|
||||
_ = &foo;
|
||||
try expect(foo.a + foo.b == 2);
|
||||
}
|
||||
@ -710,8 +710,6 @@ fn tokenizeAndPrintRaw(
|
||||
.keyword_align,
|
||||
.keyword_and,
|
||||
.keyword_asm,
|
||||
.keyword_async,
|
||||
.keyword_await,
|
||||
.keyword_break,
|
||||
.keyword_catch,
|
||||
.keyword_comptime,
|
||||
@ -748,7 +746,6 @@ fn tokenizeAndPrintRaw(
|
||||
.keyword_try,
|
||||
.keyword_union,
|
||||
.keyword_unreachable,
|
||||
.keyword_usingnamespace,
|
||||
.keyword_var,
|
||||
.keyword_volatile,
|
||||
.keyword_allowzero,
|
||||
|
||||
@ -653,8 +653,6 @@ fn tokenizeAndPrint(arena: Allocator, out: anytype, raw_src: []const u8) !void {
|
||||
.keyword_align,
|
||||
.keyword_and,
|
||||
.keyword_asm,
|
||||
.keyword_async,
|
||||
.keyword_await,
|
||||
.keyword_break,
|
||||
.keyword_catch,
|
||||
.keyword_comptime,
|
||||
@ -691,7 +689,6 @@ fn tokenizeAndPrint(arena: Allocator, out: anytype, raw_src: []const u8) !void {
|
||||
.keyword_try,
|
||||
.keyword_union,
|
||||
.keyword_unreachable,
|
||||
.keyword_usingnamespace,
|
||||
.keyword_var,
|
||||
.keyword_volatile,
|
||||
.keyword_allowzero,
|
||||
|
||||
@ -50,8 +50,6 @@ zig_keywords = {
|
||||
'anyframe',
|
||||
'anytype',
|
||||
'asm',
|
||||
'async',
|
||||
'await',
|
||||
'break',
|
||||
'callconv',
|
||||
'catch',
|
||||
@ -88,7 +86,6 @@ zig_keywords = {
|
||||
'try',
|
||||
'union',
|
||||
'unreachable',
|
||||
'usingnamespace',
|
||||
'var',
|
||||
'volatile',
|
||||
'while',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user