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:
agra
2026-06-09 11:36:04 +03:00
parent 8058be2538
commit cd7510067f
8 changed files with 98 additions and 180 deletions

View File

@@ -5,18 +5,6 @@ const errors = @import("errors.zig");
const c_import = @import("c_import.zig");
const Node = ast.Node;
/// The `*const ast.FnDecl` a function-authoring decl carries, or null when the
/// decl is not a function — either a bare `fn_decl` (`f :: (…) -> T { … }`) or a
/// `const_decl` whose value is a function. Drives the per-module `module_fns`
/// identity index (fix-0102a).
fn fnDeclOf(decl: *const Node) ?*const ast.FnDecl {
return switch (decl.data) {
.fn_decl => &decl.data.fn_decl,
.const_decl => |cd| if (cd.value.data == .fn_decl) &cd.value.data.fn_decl else null,
else => null,
};
}
/// Comptime evaluation context for the inline-if hoisting pass below.
/// Mirrors the values `injectComptimeConstants` will later push into the
/// lowering's `comptime_constants` map (OS / ARCH / POINTER_SIZE), but
@@ -451,50 +439,15 @@ pub const ResolvedModule = struct {
/// Module cache: maps resolved file paths to their ResolvedModules.
pub const ModuleCache = std.StringHashMap(ResolvedModule);
/// Per-module function identity index: function NAME → the `*const FnDecl` that
/// module AUTHORS. Mirrors a single module's slice of `module_scopes`.
pub const FnIndex = std.StringHashMap(*const ast.FnDecl);
/// `path → name → *const FnDecl`, mirroring `module_scopes`. One entry per
/// resolved module keyed by its path (a directory's combined module keyed by
/// `dir_path`); each entry indexes only what that module AUTHORS. Two modules
/// each authoring `f` are retained under their own paths — the identity index
/// fix-0102c's bare-name disambiguation consults to bind a flat call to the
/// right author.
pub const ModuleFns = std.StringHashMap(FnIndex);
/// Index a single module's authored functions (`own_decls`) into `out[path]`.
/// First-wins WITHIN a module mirrors the scan pass; cross-module same-name
/// authors live under their own `path` keys.
fn indexModuleFns(allocator: std.mem.Allocator, out: *ModuleFns, path: []const u8, own_decls: []const *Node) !void {
const gop = try out.getOrPut(path);
if (!gop.found_existing) gop.value_ptr.* = FnIndex.init(allocator);
for (own_decls) |decl| {
const fd = fnDeclOf(decl) orelse continue;
const name = decl.data.declName() orelse continue;
if (gop.value_ptr.contains(name)) continue;
try gop.value_ptr.put(name, fd);
}
}
/// Build the per-module function index from a resolved program: the main module
/// (keyed by `main_path`) plus every cached module (keyed by its own path).
/// Mirrors how `core.zig` fills `module_scopes` from `mod.scope` + the cache.
pub fn buildModuleFns(allocator: std.mem.Allocator, main_path: []const u8, main_mod: ResolvedModule, cache: *const ModuleCache, out: *ModuleFns) !void {
try indexModuleFns(allocator, out, main_path, main_mod.own_decls);
var it = cache.iterator();
while (it.next()) |entry| {
try indexModuleFns(allocator, out, entry.key_ptr.*, entry.value_ptr.own_decls);
}
}
// ── Raw import facts (the unified-resolver store; nothing consumes it yet) ──
// ── Raw import facts (the unified-resolver store) ──
//
// `buildImportFacts` produces two source-keyed views over the resolved program,
// callable WITHOUT IR lowering (the LSP reuses it later): a scalar per-module
// raw-decl index (`name → RawDeclRef`) and the namespace import edges
// (`importer → alias → NamespaceTarget`). Both are built from each module's
// `own_decls` — exactly the same modules `buildModuleFns` walks.
// `own_decls` (the main module plus every cache entry). Function authors are
// read out of `name → RawDeclRef` directly (`fnDeclOfRaw`), so there is no
// separate function-only index.
/// A named top-level declaration the resolver may select, kept as the raw AST
/// node pointer (NOT pre-classified — a `const_decl` whose value is a function
@@ -566,9 +519,9 @@ pub fn rawDeclRefOf(decl: *const Node) ?RawDeclRef {
}
/// Index one module's authored decls (`own_decls`) into `decls[path]` and record
/// any namespace aliases into `ns_edges[path]`. First-wins WITHIN a module
/// mirrors `indexModuleFns`; `own_decls` is already name-deduped by `addOwnDecl`,
/// so the first-wins guard never actually fires here.
/// any namespace aliases into `ns_edges[path]`. First-wins WITHIN a module;
/// `own_decls` is already name-deduped by `addOwnDecl`, so the first-wins guard
/// never actually fires here.
fn indexModuleDecls(
allocator: std.mem.Allocator,
decls: *ModuleDecls,
@@ -601,8 +554,8 @@ fn indexModuleDecls(
}
/// Build the raw import facts from a resolved program: the main module (keyed by
/// `main_path`) plus every cached module (keyed by its own path). The same module
/// set `buildModuleFns` walks. No IR lowering required.
/// `main_path`) plus every cached module (keyed by its own path). No IR lowering
/// required.
pub fn buildImportFacts(
allocator: std.mem.Allocator,
main_path: []const u8,