refactor(ffi-linkage): Phase 9.1d — eliminate the foreign_expr AST node
The last linkage-family 'foreign' carrier. Migrated c_import.zig auto-synthesis
(#import c {#include}) to build the extern shape (empty-block body + extern_export
= .extern_) instead of a foreign_expr body — the Phase 5.0 fn-body flip applied to
auto-synth. With nothing left building it, deleted the foreign_expr union variant +
ForeignExpr struct (ast.zig) and every reader: the dead-arm switch cases (sema,
resolver, generic, call, semantic_diagnostics, lsp), the coalescing reads in
decl.zig (is_foreign local, cc/rename/dedup/variadic/visibility gates) + pack.zig,
and checkForeignRefs (now reads extern_lib only). 9.1 LINKAGE PURGE COMPLETE — all
that remains in src/ is the runtime-class family (9.2) + comments. Snapshot-neutral
(the #import c examples 1215/1216/1217 + sqlite 1624 exercise the synth path); suite
green (646 corpus / 444 unit, 0 failed).
This commit is contained in:
@@ -82,7 +82,6 @@ pub const Node = struct {
|
|||||||
inferred_type: void,
|
inferred_type: void,
|
||||||
builtin_expr: void,
|
builtin_expr: void,
|
||||||
compiler_expr: void,
|
compiler_expr: void,
|
||||||
foreign_expr: ForeignExpr,
|
|
||||||
library_decl: LibraryDecl,
|
library_decl: LibraryDecl,
|
||||||
framework_decl: FrameworkDecl,
|
framework_decl: FrameworkDecl,
|
||||||
function_type_expr: FunctionTypeExpr,
|
function_type_expr: FunctionTypeExpr,
|
||||||
@@ -743,11 +742,6 @@ pub const NamespaceDecl = struct {
|
|||||||
is_raw: bool = false,
|
is_raw: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ForeignExpr = struct {
|
|
||||||
library_ref: ?[]const u8 = null, // identifier name of library constant
|
|
||||||
c_name: ?[]const u8 = null, // C symbol name override
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const LibraryDecl = struct {
|
pub const LibraryDecl = struct {
|
||||||
lib_name: []const u8,
|
lib_name: []const u8,
|
||||||
name: []const u8, // sx-side constant name
|
name: []const u8, // sx-side constant name
|
||||||
|
|||||||
@@ -259,11 +259,13 @@ pub fn processCImport(
|
|||||||
else
|
else
|
||||||
try mapCTypeToSxNode(allocator, ret_str);
|
try mapCTypeToSxNode(allocator, ret_str);
|
||||||
|
|
||||||
// Create foreign_expr body (no library_ref — symbols resolved at runtime)
|
// Extern-import body: an empty block + `extern_export = .extern_` (no
|
||||||
const foreign_body = try allocator.create(Node);
|
// LIB / csym — symbols resolve at runtime). Same shape the postfix
|
||||||
foreign_body.* = .{
|
// `extern` keyword produces; lowering reads `extern_export`.
|
||||||
|
const extern_body = try allocator.create(Node);
|
||||||
|
extern_body.* = .{
|
||||||
.span = .{ .start = 0, .end = 0 },
|
.span = .{ .start = 0, .end = 0 },
|
||||||
.data = .{ .foreign_expr = .{ .library_ref = null, .c_name = null } },
|
.data = .{ .block = .{ .stmts = &.{}, .produces_value = false } },
|
||||||
};
|
};
|
||||||
|
|
||||||
const fn_node = try allocator.create(Node);
|
const fn_node = try allocator.create(Node);
|
||||||
@@ -273,9 +275,10 @@ pub fn processCImport(
|
|||||||
.name = name,
|
.name = name,
|
||||||
.params = try params.toOwnedSlice(allocator),
|
.params = try params.toOwnedSlice(allocator),
|
||||||
.return_type = ret_node,
|
.return_type = ret_node,
|
||||||
.body = foreign_body,
|
.body = extern_body,
|
||||||
// A foreign C function whose own NAME collides with a reserved
|
.extern_export = .extern_,
|
||||||
// type spelling (`int i2(int);`) is RAW — exempt from the
|
// A C function whose own NAME collides with a reserved type
|
||||||
|
// spelling (`int i2(int);`) is RAW — exempt from the
|
||||||
// reserved-type-name decl check so generated bindings import
|
// reserved-type-name decl check so generated bindings import
|
||||||
// without hand-edits.
|
// without hand-edits.
|
||||||
.is_raw = true,
|
.is_raw = true,
|
||||||
@@ -332,20 +335,12 @@ fn checkForeignRefs(valid: *const std.StringHashMap(void), decls: []const *Node,
|
|||||||
for (decls) |d| {
|
for (decls) |d| {
|
||||||
switch (d.data) {
|
switch (d.data) {
|
||||||
.fn_decl => |fd| {
|
.fn_decl => |fd| {
|
||||||
// A library reference rides on the legacy `#foreign` body
|
// A library reference rides on the `extern LIB` keyword
|
||||||
// (foreign_expr.library_ref) OR the new `extern LIB` keyword
|
// (extern_lib); it must name a declared #library / #import c unit.
|
||||||
// (extern_lib); both must name a declared #library / #import c
|
if (fd.extern_export != .extern_) continue;
|
||||||
// unit. The diagnostic names the surface keyword the user wrote
|
const ref = fd.extern_lib orelse continue;
|
||||||
// so the two spellings stay self-describing.
|
|
||||||
const kw: []const u8, const ref: []const u8 = switch (fd.body.data) {
|
|
||||||
.foreign_expr => |fe| .{ "#foreign", fe.library_ref orelse continue },
|
|
||||||
else => if (fd.extern_export == .extern_)
|
|
||||||
.{ "extern", fd.extern_lib orelse continue }
|
|
||||||
else
|
|
||||||
continue,
|
|
||||||
};
|
|
||||||
if (!valid.contains(ref)) {
|
if (!valid.contains(ref)) {
|
||||||
diags.addFmt(.err, d.span, "{s} library '{s}' is not declared; expected a #library constant or a named '#import c' unit", .{ kw, ref });
|
diags.addFmt(.err, d.span, "extern library '{s}' is not declared; expected a #library constant or a named '#import c' unit", .{ref});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.namespace_decl => |ns| checkForeignRefs(valid, ns.decls, diags),
|
.namespace_decl => |ns| checkForeignRefs(valid, ns.decls, diags),
|
||||||
|
|||||||
@@ -726,7 +726,7 @@ pub fn lowerCall(self: *Lowering, c_in: *const ast.Call) Ref {
|
|||||||
// literal global symbol — the existing bare-name
|
// literal global symbol — the existing bare-name
|
||||||
// machinery below resolves them.
|
// machinery below resolves them.
|
||||||
switch (fd.body.data) {
|
switch (fd.body.data) {
|
||||||
.foreign_expr, .builtin_expr, .compiler_expr => break :gate,
|
.builtin_expr, .compiler_expr => break :gate,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
if (hasComptimeParams(fd)) return self.lowerComptimeCall(fd, c);
|
if (hasComptimeParams(fd)) return self.lowerComptimeCall(fd, c);
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ pub fn funcWantsImplicitCtx(self: *const Lowering, fd: *const ast.FnDecl) bool {
|
|||||||
// C ABI, no sx context (Phase 2, gap iv).
|
// C ABI, no sx context (Phase 2, gap iv).
|
||||||
if (fd.extern_export != .none) return false;
|
if (fd.extern_export != .none) return false;
|
||||||
return switch (fd.body.data) {
|
return switch (fd.body.data) {
|
||||||
.foreign_expr, .builtin_expr, .compiler_expr => false,
|
.builtin_expr, .compiler_expr => false,
|
||||||
else => !isExportedEntryName(fd.name),
|
else => !isExportedEntryName(fd.name),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -2084,21 +2084,18 @@ pub fn declareFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8)
|
|||||||
// Foreign declarations with a trailing variadic param map to the C
|
// Foreign declarations with a trailing variadic param map to the C
|
||||||
// calling convention's `...` tail. Drop the variadic param from the
|
// calling convention's `...` tail. Drop the variadic param from the
|
||||||
// IR signature (it has no C-level slot) and set is_variadic.
|
// IR signature (it has no C-level slot) and set is_variadic.
|
||||||
const is_foreign = fd.body.data == .foreign_expr;
|
// Bare `extern` import: an external C symbol declared via the `extern`
|
||||||
// Bare `extern` import: an external C symbol declared via the new linkage
|
// linkage keyword (empty-block placeholder body). C-ABI promotion +
|
||||||
// surface (empty-block placeholder body, no `foreign_expr`). It shares
|
// declareExtern routing below; the optional `extern LIB "csym"` lib/rename
|
||||||
// `#foreign`'s C-ABI promotion + declareExtern routing below; the optional
|
// axis is extern_lib/extern_name. (`export` defines take the beginFunction
|
||||||
// `extern LIB "csym"` lib/rename axis (extern_lib/extern_name) is consumed
|
// path, not here.) The `#import c` auto-synthesis also produces this shape.
|
||||||
// in Phase 1.2. (`export` defines take the beginFunction path, not here.)
|
|
||||||
const is_extern_decl = fd.extern_export == .extern_;
|
const is_extern_decl = fd.extern_export == .extern_;
|
||||||
var is_variadic = false;
|
var is_variadic = false;
|
||||||
var effective_params = fd.params;
|
var effective_params = fd.params;
|
||||||
// The C-variadic `...` tail applies to BOTH lib-less C-import spellings:
|
// A lib-less C-import with a C-variadic `...` tail: drop the trailing slice
|
||||||
// the legacy `#foreign` (foreign_expr body) and the new `extern` keyword.
|
// param and set is_variadic (mirrored at the call site by
|
||||||
// A migrated variadic `extern` must drop the trailing slice param and set
|
// `packVariadicCallArgs`).
|
||||||
// the flag exactly as its `#foreign` twin did (mirrored at the call site
|
if (is_extern_decl and fd.params.len > 0 and fd.params[fd.params.len - 1].is_variadic) {
|
||||||
// by `packVariadicCallArgs`).
|
|
||||||
if ((is_foreign or is_extern_decl) and fd.params.len > 0 and fd.params[fd.params.len - 1].is_variadic) {
|
|
||||||
is_variadic = true;
|
is_variadic = true;
|
||||||
effective_params = fd.params[0 .. fd.params.len - 1];
|
effective_params = fd.params[0 .. fd.params.len - 1];
|
||||||
}
|
}
|
||||||
@@ -2119,23 +2116,19 @@ pub fn declareFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8)
|
|||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// `#foreign` declarations are external C symbols by definition —
|
// `extern` declarations are external C symbols by definition — promote
|
||||||
// promote them to callconv(.c) when the user didn't write it
|
// them to callconv(.c) when the user didn't write it explicitly. This keeps
|
||||||
// explicitly. This keeps fn-ptr coercion type-safe: anything
|
// fn-ptr coercion type-safe: anything typed by name as `(args) -> ret` of an
|
||||||
// typed by name as `(args) -> ret` of a `#foreign` decl can be
|
// `extern` decl can be assigned to / passed as a `callconv(.c)` fn-pointer
|
||||||
// assigned to / passed as a `callconv(.c)` fn-pointer without a
|
// without a call-convention mismatch.
|
||||||
// call-convention mismatch.
|
const cc: Function.CallingConvention = if (fd.call_conv == .c or is_extern_decl or fd.extern_export == .export_) .c else .default;
|
||||||
const cc: Function.CallingConvention = if (fd.call_conv == .c or is_foreign or is_extern_decl or fd.extern_export == .export_) .c else .default;
|
|
||||||
|
|
||||||
// Symbol-name override: `#foreign … "csym"` (foreign_expr.c_name) or the new
|
// Symbol-name override: `extern … "csym"` / `export … "csym"` (fd.extern_name).
|
||||||
// `extern … "csym"` / `export … "csym"` (fd.extern_name). Declare under the C
|
// Declare under the C name and map the sx name → C name so call sites resolve
|
||||||
// name and map the sx name → C name so call sites resolve to the real symbol.
|
// to the real symbol. For `export` the stub is later promoted to a real
|
||||||
// For `export` the stub is later promoted to a real definition (the body
|
// definition (the body lowers into this C-named function via lazyLowerFunction).
|
||||||
// lowers into this C-named function via lazyLowerFunction — Phase 2.2).
|
|
||||||
const is_export_decl = fd.extern_export == .export_;
|
const is_export_decl = fd.extern_export == .export_;
|
||||||
const rename_c_name: ?[]const u8 = if (is_foreign)
|
const rename_c_name: ?[]const u8 = if (is_extern_decl or is_export_decl)
|
||||||
fd.body.data.foreign_expr.c_name
|
|
||||||
else if (is_extern_decl or is_export_decl)
|
|
||||||
fd.extern_name
|
fd.extern_name
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
@@ -2157,7 +2150,7 @@ pub fn declareFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const name_id = self.module.types.internString(name);
|
const name_id = self.module.types.internString(name);
|
||||||
if ((is_foreign or is_extern_decl) and self.dedupeExternSymbol(fd, name_id, params.items, ret_ty)) return;
|
if (is_extern_decl and self.dedupeExternSymbol(fd, name_id, params.items, ret_ty)) return;
|
||||||
const fid = self.builder.declareExtern(name_id, params.items, ret_ty);
|
const fid = self.builder.declareExtern(name_id, params.items, ret_ty);
|
||||||
const func = self.module.getFunctionMut(fid);
|
const func = self.module.getFunctionMut(fid);
|
||||||
func.call_conv = cc;
|
func.call_conv = cc;
|
||||||
@@ -2204,7 +2197,7 @@ pub fn registerQualifiedFn(self: *Lowering, ns_name: []const u8, fd: *const ast.
|
|||||||
// Foreign / builtin / #compiler bodies keep their literal name; a
|
// Foreign / builtin / #compiler bodies keep their literal name; a
|
||||||
// qualified alias has no distinct symbol to resolve to.
|
// qualified alias has no distinct symbol to resolve to.
|
||||||
switch (fd.body.data) {
|
switch (fd.body.data) {
|
||||||
.foreign_expr, .builtin_expr, .compiler_expr => return,
|
.builtin_expr, .compiler_expr => return,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
const qualified = std.fmt.allocPrint(self.alloc, "{s}.{s}", .{ ns_name, short }) catch return;
|
const qualified = std.fmt.allocPrint(self.alloc, "{s}.{s}", .{ ns_name, short }) catch return;
|
||||||
@@ -2251,28 +2244,16 @@ pub fn isVisible(self: *Lowering, name: []const u8, vis: resolver_mod.Visibility
|
|||||||
// this predicate is single-hop only.
|
// this predicate is single-hop only.
|
||||||
.impl_transitive => @panic("isVisible: transitive visibility is owned by findVisibleImpls"),
|
.impl_transitive => @panic("isVisible: transitive visibility is owned by findVisibleImpls"),
|
||||||
.c_import_bare => {
|
.c_import_bare => {
|
||||||
// Foreign-C gate: only a lib-less C-import fn_decl is policed; a
|
// Extern-C gate: only a lib-less C-import fn_decl is policed; a
|
||||||
// library-bound decl (resolves via the named library, not a
|
// library-bound `extern LIB` decl (resolves via the named library,
|
||||||
// module edge) or a non-C body is unconditionally visible. The
|
// not a module edge) or a non-extern body is unconditionally
|
||||||
// legacy `#foreign` form (a `foreign_expr` body) and the new
|
// visible. A lib-less `extern` decl routes to `visibleOverEdges` so
|
||||||
// `extern` keyword (`extern_export == .extern_`, empty-block body)
|
// a transitive reference gets the "C function not visible"
|
||||||
// are two spellings of the same lib-less C-symbol import, so BOTH
|
// diagnostic, not the generic top-level-name wording (example 1228).
|
||||||
// route to `visibleOverEdges` here — a migrated `extern` decl must
|
|
||||||
// get the identical "C function not visible" diagnostic its
|
|
||||||
// `#foreign` twin did, not the generic top-level-name wording
|
|
||||||
// (FFI-linkage Part B; example 1228).
|
|
||||||
const fd = self.program_index.fn_ast_map.get(name) orelse return true;
|
const fd = self.program_index.fn_ast_map.get(name) orelse return true;
|
||||||
switch (fd.body.data) {
|
if (fd.extern_export != .extern_) return true;
|
||||||
.foreign_expr => |fe| {
|
if (fd.extern_lib != null) return true;
|
||||||
if (fe.library_ref != null) return true;
|
return self.visibleOverEdges(name);
|
||||||
return self.visibleOverEdges(name);
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
if (fd.extern_export != .extern_) return true;
|
|
||||||
if (fd.extern_lib != null) return true;
|
|
||||||
return self.visibleOverEdges(name);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
.user_bare_flat => return self.visibleOverEdges(name),
|
.user_bare_flat => return self.visibleOverEdges(name),
|
||||||
}
|
}
|
||||||
@@ -2325,7 +2306,7 @@ pub fn lazyLowerFunction(self: *Lowering, name: []const u8) void {
|
|||||||
// a fresh ct_module via `evalComptimeString`) emits `.call` against a
|
// a fresh ct_module via `evalComptimeString`) emits `.call` against a
|
||||||
// FuncId that doesn't exist locally; the interp can't find the
|
// FuncId that doesn't exist locally; the interp can't find the
|
||||||
// foreign target and silently no-ops instead of dispatching to libc.
|
// foreign target and silently no-ops instead of dispatching to libc.
|
||||||
if (fd.body.data == .foreign_expr or fd.extern_export == .extern_) {
|
if (fd.extern_export == .extern_) {
|
||||||
if (self.resolveFuncByName(name) == null) {
|
if (self.resolveFuncByName(name) == null) {
|
||||||
self.declareFunction(fd, name);
|
self.declareFunction(fd, name);
|
||||||
self.lowered_functions.put(name, {}) catch {};
|
self.lowered_functions.put(name, {}) catch {};
|
||||||
@@ -2532,7 +2513,7 @@ pub fn lowerFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8, i
|
|||||||
|
|
||||||
// Check if the function body is a builtin or foreign declaration (no body
|
// Check if the function body is a builtin or foreign declaration (no body
|
||||||
// needed). `extern` imports are declare-only too (empty placeholder body).
|
// needed). `extern` imports are declare-only too (empty placeholder body).
|
||||||
if (fd.body.data == .builtin_expr or fd.body.data == .foreign_expr or fd.body.data == .compiler_expr or fd.extern_export == .extern_) {
|
if (fd.body.data == .builtin_expr or fd.body.data == .compiler_expr or fd.extern_export == .extern_) {
|
||||||
// Already declared by scanDecls/declareFunction (which handles #foreign renames)
|
// Already declared by scanDecls/declareFunction (which handles #foreign renames)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -819,7 +819,7 @@ pub fn isPlainFreeFn(fd: *const ast.FnDecl) bool {
|
|||||||
// fn. `export` DEFINES a real body, so it stays plain-free.
|
// fn. `export` DEFINES a real body, so it stays plain-free.
|
||||||
if (fd.extern_export == .extern_) return false;
|
if (fd.extern_export == .extern_) return false;
|
||||||
return switch (fd.body.data) {
|
return switch (fd.body.data) {
|
||||||
.foreign_expr, .builtin_expr, .compiler_expr => false,
|
.builtin_expr, .compiler_expr => false,
|
||||||
else => true,
|
else => true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,12 +296,12 @@ pub fn lowerVariadicArgs(self: *Lowering, param_name: []const u8, call_args: []c
|
|||||||
/// Detects variadic params in the function decl, packs remaining args into a typed slice,
|
/// Detects variadic params in the function decl, packs remaining args into a typed slice,
|
||||||
/// and replaces the args list with [fixed_args..., slice_ref].
|
/// and replaces the args list with [fixed_args..., slice_ref].
|
||||||
pub fn packVariadicCallArgs(self: *Lowering, fd: *const ast.FnDecl, c: *const ast.Call, args: *std.ArrayList(Ref)) void {
|
pub fn packVariadicCallArgs(self: *Lowering, fd: *const ast.FnDecl, c: *const ast.Call, args: *std.ArrayList(Ref)) void {
|
||||||
// A lib-less C-import variadic — `#foreign` (foreign_expr body) OR the new
|
// A lib-less C-import variadic via the `extern` keyword (or `#import c`
|
||||||
// `extern` keyword — uses the C calling convention's `...` tail: extras are
|
// `extern` keyword — uses the C calling convention's `...` tail: extras are
|
||||||
// passed through directly with default argument promotion (handled at the
|
// passed through directly with default argument promotion (handled at the
|
||||||
// call site), not packed into an sx slice. Mirrors the `is_variadic` drop
|
// call site), not packed into an sx slice. Mirrors the `is_variadic` drop
|
||||||
// in `declareFunction`.
|
// in `declareFunction`.
|
||||||
if ((fd.body.data == .foreign_expr or fd.extern_export == .extern_) and
|
if ((fd.extern_export == .extern_) and
|
||||||
fd.params.len > 0 and fd.params[fd.params.len - 1].is_variadic)
|
fd.params.len > 0 and fd.params[fd.params.len - 1].is_variadic)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ pub fn isPlainFreeFnDecl(fd: *const ast.FnDecl) bool {
|
|||||||
// body, so it stays plain-free.
|
// body, so it stays plain-free.
|
||||||
if (fd.extern_export == .extern_) return false;
|
if (fd.extern_export == .extern_) return false;
|
||||||
return switch (fd.body.data) {
|
return switch (fd.body.data) {
|
||||||
.foreign_expr, .builtin_expr, .compiler_expr => false,
|
.builtin_expr, .compiler_expr => false,
|
||||||
else => true,
|
else => true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -351,7 +351,6 @@ pub const UnknownTypeChecker = struct {
|
|||||||
.inferred_type,
|
.inferred_type,
|
||||||
.builtin_expr,
|
.builtin_expr,
|
||||||
.compiler_expr,
|
.compiler_expr,
|
||||||
.foreign_expr,
|
|
||||||
.framework_decl,
|
.framework_decl,
|
||||||
.function_type_expr,
|
.function_type_expr,
|
||||||
.closure_type_expr,
|
.closure_type_expr,
|
||||||
|
|||||||
@@ -1325,7 +1325,7 @@ pub const Server = struct {
|
|||||||
// Skip functions, types, structs, enums, unions, comptime, foreign, library
|
// Skip functions, types, structs, enums, unions, comptime, foreign, library
|
||||||
switch (cd.value.data) {
|
switch (cd.value.data) {
|
||||||
.fn_decl, .type_expr, .struct_decl, .enum_decl, .union_decl,
|
.fn_decl, .type_expr, .struct_decl, .enum_decl, .union_decl,
|
||||||
.comptime_expr, .foreign_expr, .library_decl,
|
.comptime_expr, .library_decl,
|
||||||
=> return,
|
=> return,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1295,7 +1295,6 @@ pub const Analyzer = struct {
|
|||||||
.inferred_type,
|
.inferred_type,
|
||||||
.builtin_expr,
|
.builtin_expr,
|
||||||
.compiler_expr,
|
.compiler_expr,
|
||||||
.foreign_expr,
|
|
||||||
.library_decl,
|
.library_decl,
|
||||||
.framework_decl,
|
.framework_decl,
|
||||||
.function_type_expr,
|
.function_type_expr,
|
||||||
@@ -1761,7 +1760,6 @@ pub fn findNodeAtOffset(node: *Node, offset: u32) ?*Node {
|
|||||||
.inferred_type,
|
.inferred_type,
|
||||||
.builtin_expr,
|
.builtin_expr,
|
||||||
.compiler_expr,
|
.compiler_expr,
|
||||||
.foreign_expr,
|
|
||||||
.library_decl,
|
.library_decl,
|
||||||
.framework_decl,
|
.framework_decl,
|
||||||
.function_type_expr,
|
.function_type_expr,
|
||||||
|
|||||||
Reference in New Issue
Block a user