fix(imports): keep merged scope first-wins; index dups in module_fns only [0102a]
Attempt-1 retained a same-name cross-module FUNCTION author in the merged decl list (mergeFlat + the directory merge), which is the list the existing first-wins resolver consumes. That changed the data feeding resolution (`mod.decls` carried two `greet`), violating this step's purpose: additive indexes with ZERO resolution change. Revert both merge sites to byte-for-byte first-wins, exactly as on wt-fix-0102-base. The dropped same-name author is still retained — but only in the SEPARATE `module_fns` index, which is built from each module's `own_decls` (un-deduped, per-path) and which nothing reads yet. The `flat_import_graph` side data is likewise untouched. Both are foundation for fix-0102c's bare-name disambiguation; current resolution is unchanged. Drop the now-unused `declAuthorsFn` helper (its only callers were the two merge sites). `fnDeclOf` stays — it feeds the index. Tests: the existing unit test now asserts the merged scope stays first-wins (one `greet`, a.sx's author) while `module_fns` still retains BOTH authors and `flat_import_graph` excludes the namespaced edge. Add a mixed non-fn/fn collision test asserting the merged scope keeps a.sx's struct (first-wins), unchanged by the function author.
This commit is contained in:
@@ -5,24 +5,10 @@ const errors = @import("errors.zig");
|
||||
const c_import = @import("c_import.zig");
|
||||
const Node = ast.Node;
|
||||
|
||||
/// True iff `decl` authors a top-level FUNCTION — either a bare `fn_decl`
|
||||
/// (`f :: (…) -> T { … }`) or a `const_decl` whose value is a function
|
||||
/// (`f :: (…) { … }` parsed as a const-bound fn). Used by the flat / directory
|
||||
/// merge to retain a same-name function authored by a DIFFERENT module instead
|
||||
/// of first-wins dropping it (fix-0102a): a flat importer that pulls two modules
|
||||
/// each authoring `f` needs BOTH decls reachable downstream. Non-function decls
|
||||
/// keep first-wins dedup.
|
||||
fn declAuthorsFn(decl: *const Node) bool {
|
||||
return switch (decl.data) {
|
||||
.fn_decl => true,
|
||||
.const_decl => |cd| cd.value.data == .fn_decl,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// The `*const ast.FnDecl` a function-authoring decl carries, or null when the
|
||||
/// decl is not a function (mirrors `declAuthorsFn`). Drives the per-module
|
||||
/// `module_fns` identity index (fix-0102a).
|
||||
/// 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,
|
||||
@@ -360,13 +346,8 @@ pub const ResolvedModule = struct {
|
||||
for (other.decls) |decl| {
|
||||
if (seen_nodes.contains(decl)) continue;
|
||||
if (decl.data.declName()) |name| {
|
||||
if (seen_list.contains(name)) {
|
||||
// First-wins dedup for non-functions; retain a same-name
|
||||
// FUNCTION authored by a different module (fix-0102a).
|
||||
if (!declAuthorsFn(decl)) continue;
|
||||
} else {
|
||||
try seen_list.put(name, {});
|
||||
}
|
||||
if (seen_list.contains(name)) continue;
|
||||
try seen_list.put(name, {});
|
||||
}
|
||||
try seen_nodes.put(decl, {});
|
||||
try list.append(allocator, decl);
|
||||
@@ -787,13 +768,8 @@ fn resolveDirectoryImport(
|
||||
for (file_mod.decls) |decl| {
|
||||
if (seen_nodes.contains(decl)) continue;
|
||||
if (decl.data.declName()) |name| {
|
||||
if (seen_in_list.contains(name)) {
|
||||
// First-wins dedup for non-functions; retain a same-name
|
||||
// FUNCTION authored by a different file (fix-0102a).
|
||||
if (!declAuthorsFn(decl)) continue;
|
||||
} else {
|
||||
try seen_in_list.put(name, {});
|
||||
}
|
||||
if (seen_in_list.contains(name)) continue;
|
||||
try seen_in_list.put(name, {});
|
||||
}
|
||||
try seen_nodes.put(decl, {});
|
||||
try decl_list.append(allocator, decl);
|
||||
|
||||
Reference in New Issue
Block a user