refactor(stdlib/S1.2): delete module_fns; dissolve legacy_direct_any [additive]
Delete module_fns as a separate function-author fact source. Its authors already live in the module_decls raw facts, so lowerRetainedSameNameAuthors now reads function authors straight out of module_decls (filtered to *FnDecl via fnDeclOfRaw) — the same path → name → RawDeclRef store, fn-filtered. Remove imports.ModuleFns / FnIndex / indexModuleFns / buildModuleFns / fnDeclOf, the Compilation.module_fns field + its build + wiring, and ProgramIndex.module_fns. Remove VisibilityMode.legacy_direct_any (the quarantined own-scope-plus-full- import_graph mode): no production caller passed it, so the collectVisibleAuthors and isVisible switch arms that handled it are dead and go too, collapsing VisEdgeSet to the single flat-import walk. No semantic fallback is introduced; import_graph stays the transitive-visibility source for findVisibleImpls. Additive: the old maps stay active and lowering still consumes them — no lowering consumer is cut over to the DeclTable (that is S3), and no resolution behavior changes. Tests that drove the removed symbols are rerouted through module_decls / the flat-edge walk. Gate over the baseline-green corpus: zig build, zig build test (424/424), bash tests/run_examples.sh (540 passed) — all exit 0; single-author output byte-identical; multi-author 0722–0740 stdout/exit unchanged.
This commit is contained in:
@@ -986,10 +986,10 @@ pub const Lowering = struct {
|
||||
// Declare extern stub for all functions (bodies lowered
|
||||
// lazily). Key the identity map (`fn_decl_fids`, inside
|
||||
// `declareFunction`) by the STABLE AST field pointer — the
|
||||
// same `&decl.data.fn_decl` stored in `fn_ast_map` and
|
||||
// `module_fns` — not the switch-capture copy `fd`, whose
|
||||
// address is a per-iteration stack temporary that no later
|
||||
// decl-identity lookup can reproduce.
|
||||
// same `&decl.data.fn_decl` stored in `fn_ast_map` and the
|
||||
// `module_decls` raw facts — not the switch-capture copy `fd`,
|
||||
// whose address is a per-iteration stack temporary that no
|
||||
// later decl-identity lookup can reproduce.
|
||||
self.declareFunction(&decl.data.fn_decl, fd.name);
|
||||
},
|
||||
.const_decl => |cd| {
|
||||
@@ -1741,35 +1741,36 @@ pub const Lowering = struct {
|
||||
/// The first-wins flat/directory merge keeps exactly one author per name in
|
||||
/// the merged decl list; `scanDecls` declares that WINNER (lowered on demand
|
||||
/// through the name-keyed `lazyLowerFunction`). fix-0102a retained every
|
||||
/// dropped same-name author in `module_fns` (path → name → `*FnDecl`) without
|
||||
/// touching resolution; this walks that index and gives each shadowed author
|
||||
/// its own slot: `declareFunction` (identity-mapped to a fresh same-name
|
||||
/// FuncId) + `lowerFunctionBodyInto` (its body, in its own module's
|
||||
/// dropped same-name author in the `module_decls` raw facts (path → name →
|
||||
/// `RawDeclRef`) without touching resolution; this walks that index, filters
|
||||
/// each author to its `*FnDecl` (`fnDeclOfRaw`), and gives each shadowed
|
||||
/// author its own slot: `declareFunction` (identity-mapped to a fresh
|
||||
/// same-name FuncId) + `lowerFunctionBodyInto` (its body, in its own module's
|
||||
/// visibility context). Two same-name authors then carry distinct FuncIds and
|
||||
/// distinct bodies, while `resolveFuncByName` still returns the first (winner)
|
||||
/// author so existing calls bind first-wins.
|
||||
///
|
||||
/// Scoped to DIRECT flat imports of the main file: a `module_fns` entry whose
|
||||
/// path is the main file or one of its bare `#import` edges. A namespaced
|
||||
/// (`ns :: #import`) author has no bare-name winner and is excluded both by
|
||||
/// that flat-edge gate and by the `fn_ast_map` winner lookup below.
|
||||
/// Scoped to DIRECT flat imports of the main file: a `module_decls` entry
|
||||
/// whose path is the main file or one of its bare `#import` edges. A
|
||||
/// namespaced (`ns :: #import`) author has no bare-name winner and is excluded
|
||||
/// both by that flat-edge gate and by the `fn_ast_map` winner lookup below.
|
||||
pub fn lowerRetainedSameNameAuthors(self: *Lowering) void {
|
||||
const module_fns = self.program_index.module_fns orelse return;
|
||||
const module_decls = self.program_index.module_decls orelse return;
|
||||
const main_file = self.main_file orelse return;
|
||||
const flat_graph = self.program_index.flat_import_graph orelse return;
|
||||
const main_flat_edges = flat_graph.get(main_file);
|
||||
|
||||
var path_it = module_fns.iterator();
|
||||
var path_it = module_decls.iterator();
|
||||
while (path_it.next()) |path_entry| {
|
||||
const path = path_entry.key_ptr.*;
|
||||
const is_eligible = std.mem.eql(u8, path, main_file) or
|
||||
(main_flat_edges != null and main_flat_edges.?.contains(path));
|
||||
if (!is_eligible) continue;
|
||||
|
||||
var fn_it = path_entry.value_ptr.iterator();
|
||||
var fn_it = path_entry.value_ptr.names.iterator();
|
||||
while (fn_it.next()) |fn_entry| {
|
||||
const name = fn_entry.key_ptr.*;
|
||||
const fd = fn_entry.value_ptr.*;
|
||||
const fd = fnDeclOfRaw(fn_entry.value_ptr.*) orelse continue;
|
||||
|
||||
// A name with no bare winner is namespaced-only (`ns.fn`) — it
|
||||
// never participated in the flat merge, so it has no shadow to
|
||||
@@ -1871,18 +1872,18 @@ pub const Lowering = struct {
|
||||
/// THE plain bare-name call selector (fix-0102c, R5 §C). `resolveBareCallee`'s
|
||||
/// body verbatim, now over the Phase B author collector
|
||||
/// (`resolver.collectVisibleAuthors` — the ONE graph-walk) instead of a direct
|
||||
/// `module_fns` + `flat_import_graph` traversal. Routes a bare identifier call
|
||||
/// `name` from `caller_file` to the right same-name author when flat imports
|
||||
/// introduce a genuine collision. Every single-author / local / parameter /
|
||||
/// std / qualified name resolves through the EXISTING path unchanged: the
|
||||
/// selector returns `.none` whenever the outcome would match first-wins, so
|
||||
/// nothing on the common path is perturbed.
|
||||
/// `module_decls` + `flat_import_graph` traversal. Routes a bare identifier
|
||||
/// call `name` from `caller_file` to the right same-name author when flat
|
||||
/// imports introduce a genuine collision. Every single-author / local /
|
||||
/// parameter / std / qualified name resolves through the EXISTING path
|
||||
/// unchanged: the selector returns `.none` whenever the outcome would match
|
||||
/// first-wins, so nothing on the common path is perturbed.
|
||||
///
|
||||
/// The collector returns RAW authors across ALL decl domains; this selector
|
||||
/// reproduces `module_fns`' fn-only view by filtering each author through
|
||||
/// `fnDeclOfRaw` (a `const`-wrapped fn unwraps to its inner fn — the exact
|
||||
/// `*FnDecl` `module_fns` stored; every other domain drops out), preserving
|
||||
/// resolveBareCallee's negative space byte-for-byte.
|
||||
/// reproduces a fn-only author view by filtering each author through
|
||||
/// `fnDeclOfRaw` (a `const`-wrapped fn unwraps to its inner fn; every other
|
||||
/// domain drops out), preserving resolveBareCallee's negative space
|
||||
/// byte-for-byte.
|
||||
///
|
||||
/// - **own-author wins**: if `caller_file` authors `name` as a fn and the
|
||||
/// bare-name first-wins winner is a DIFFERENT author, select the caller's
|
||||
@@ -1910,8 +1911,8 @@ pub const Lowering = struct {
|
||||
|
||||
// own-author wins. The collector's `own` spans all domains; a non-fn
|
||||
// (or a const not bound to a function) means `caller_file` has no fn
|
||||
// `name` — fall through to the flat authors, exactly as the fn-only
|
||||
// `module_fns` walk did.
|
||||
// `name` — fall through to the flat authors, exactly as a fn-only walk
|
||||
// would.
|
||||
if (set.own) |own_author| {
|
||||
if (fnDeclOfRaw(own_author.raw)) |own| {
|
||||
if (winner != null and winner.? == own) return .none;
|
||||
@@ -2378,10 +2379,10 @@ pub const Lowering = struct {
|
||||
}
|
||||
|
||||
/// The `*FnDecl` a raw author wraps, or null when the author is not a
|
||||
/// function — `imports.fnDeclOf` over a `RawDeclRef` so the collector's
|
||||
/// all-domain authors reproduce `module_fns`' fn-only view (a `const`-wrapped
|
||||
/// fn unwraps to its inner fn, the same pointer `module_fns` holds; every
|
||||
/// other domain → null).
|
||||
/// function — unwraps a `RawDeclRef` so the collector's all-domain authors
|
||||
/// yield a fn-only view (a `const`-wrapped fn unwraps to its inner fn; every
|
||||
/// other domain → null). The single place function authors are read out of
|
||||
/// the `module_decls` raw facts.
|
||||
fn fnDeclOfRaw(ref: resolver_mod.RawDeclRef) ?*const ast.FnDecl {
|
||||
return switch (ref) {
|
||||
.fn_decl => |fd| fd,
|
||||
@@ -2633,27 +2634,20 @@ pub const Lowering = struct {
|
||||
const fd = self.program_index.fn_ast_map.get(name) orelse return true;
|
||||
if (fd.body.data != .foreign_expr) return true;
|
||||
if (fd.body.data.foreign_expr.library_ref != null) return true;
|
||||
return self.visibleOverEdges(name, .flat);
|
||||
return self.visibleOverEdges(name);
|
||||
},
|
||||
.user_bare_flat => return self.visibleOverEdges(name, .flat),
|
||||
.legacy_direct_any => return self.visibleOverEdges(name, .all),
|
||||
.user_bare_flat => return self.visibleOverEdges(name),
|
||||
}
|
||||
}
|
||||
|
||||
const VisEdgeSet = enum { flat, all };
|
||||
|
||||
/// Resolve the mode's edge set and run the per-file visibility walk. Falls
|
||||
/// Run the per-file visibility walk over the flat-import edge set. Falls
|
||||
/// open (visible) when the scoping infrastructure isn't wired (comptime
|
||||
/// callers, directory imports without main_file, etc.). The caller is
|
||||
/// responsible for restricting the check to names that ARE known top-level
|
||||
/// decls; otherwise every local variable would be policed.
|
||||
fn visibleOverEdges(self: *Lowering, name: []const u8, edges: VisEdgeSet) bool {
|
||||
fn visibleOverEdges(self: *Lowering, name: []const u8) bool {
|
||||
const source = self.current_source_file orelse return true;
|
||||
const graph = switch (edges) {
|
||||
.flat => self.program_index.flat_import_graph,
|
||||
.all => self.program_index.import_graph,
|
||||
};
|
||||
return nameVisibleOverEdges(self.program_index.module_scopes, graph, source, name);
|
||||
return nameVisibleOverEdges(self.program_index.module_scopes, self.program_index.flat_import_graph, source, name);
|
||||
}
|
||||
|
||||
/// Check if a C-imported function is visible from the current source file.
|
||||
|
||||
Reference in New Issue
Block a user