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

@@ -4,8 +4,7 @@
// resolveImports → buildImportFacts, the exact path core.zig drives) plus one
// synthetic diamond fixture for pointer-identity dedup. The visibility-adapter
// tests pin the nameVisibleOverEdges edge-walk that isNameVisible /
// isCImportVisible run on top of — including the user_bare_flat vs the
// over-permissive legacy_direct_any distinction.
// isCImportVisible run on top of — the flat-edge set vs the full import_graph.
const std = @import("std");
const ast = @import("../ast.zig");
@@ -82,8 +81,8 @@ fn tag(ref: resolver.RawDeclRef) std.meta.Tag(resolver.RawDeclRef) {
// ── collectVisibleAuthors ────────────────────────────────────────────────
// own author present; two distinct flat authors both returned RAW; and the
// user_bare_flat edge set EXCLUDES a namespaced-only import that the quarantined
// legacy_direct_any set still reaches.
// user_bare_flat edge set EXCLUDES a namespaced-only import (reachable only over
// a non-flat edge).
test "resolver: collectVisibleAuthors — own author, two distinct flat authors, namespaced edge excluded" {
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit();
@@ -129,16 +128,10 @@ test "resolver: collectVisibleAuthors — own author, two distinct flat authors,
try std.testing.expect(dup_set.flat[0].raw.fn_decl != dup_set.flat[1].raw.fn_decl);
// `secret` is authored only in p.sx, imported NAMESPACED (`g :: #import`).
// user_bare_flat must NOT see it (p.sx is not a flat edge)...
// user_bare_flat must NOT see it (p.sx is not a flat edge).
const flat_secret = r.collectVisibleAuthors("secret", main_path, .user_bare_flat);
try std.testing.expect(flat_secret.own == null);
try std.testing.expectEqual(@as(usize, 0), flat_secret.flat.len);
// ...but the quarantined legacy_direct_any set (import_graph) still reaches
// it — the exact over-permissiveness user_bare_flat tightens away.
const any_secret = r.collectVisibleAuthors("secret", main_path, .legacy_direct_any);
try std.testing.expect(any_secret.own == null);
try std.testing.expectEqual(@as(usize, 1), any_secret.flat.len);
}
// Diamond: the SAME author node is reachable over two flat edges. It must
@@ -234,10 +227,10 @@ test "resolver: collectNamespaceAuthors — returns target members, walks no gra
// ── visibility predicate (the isNameVisible / isCImportVisible core) ──────
// nameVisibleOverEdges is what isVisible(.user_bare_flat) (=> .flat graph) and
// the quarantined legacy_direct_any (=> import_graph) run on. They agree on own
// + flat names and differ ONLY on a namespaced-only name — the byte-identical
// behavior the adapters preserve vs the over-permissive set they avoid.
// nameVisibleOverEdges is the edge-walk isVisible(.user_bare_flat) runs on (the
// flat graph). Walked over the flat set vs the full import_graph, the two agree
// on own + flat names and differ ONLY on a namespaced-only name — the flat set
// the bare-name predicate uses, contrasted with the over-permissive full set.
test "resolver: visibility edge-walk — own + flat visible; namespaced-only only under import_graph" {
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit();
@@ -275,7 +268,7 @@ test "resolver: visibility edge-walk — own + flat visible; namespaced-only onl
try std.testing.expect(lower.nameVisibleOverEdges(&scopes, &all, "main", "dup"));
// Namespaced-only name: NOT visible under the flat set (user_bare_flat),
// but visible under the import_graph set (legacy_direct_any).
// but visible under the full import_graph set.
try std.testing.expect(!lower.nameVisibleOverEdges(&scopes, &flat, "main", "secret"));
try std.testing.expect(lower.nameVisibleOverEdges(&scopes, &all, "main", "secret"));