fix(lower): bare-call resolver skips non-plain authors before ambiguity gate [0102c F3]

resolveBareCallee's flat-collect branch counted ALL same-name authors —
including #foreign / generic / builtin / #compiler — before the
isPlainFreeFn filter, so two flat-imported modules each #foreign-ing the
same libc symbol under one sx name returned `.ambiguous` and errored,
instead of falling to `.none` and the existing first-wins foreign path
(master behavior). Filter authors to plain free functions DURING
collection, before the count/ambiguity determination: a non-plain
collision now yields 0 reroutable authors -> `.none`; genuine plain-fn
collisions still yield >= 2 -> `.ambiguous` (0724 unchanged). The
now-redundant single-author isPlainFreeFn check is dropped.

Regression: examples/0729-modules-flat-same-name-foreign — two flat FILE
imports each #foreign the same libc "abs" under name `absval`; a bare
call resolves first-wins and runs (exit 0). Fails-before on this branch
(ambiguity error), passes-after.
This commit is contained in:
agra
2026-06-06 15:31:14 +03:00
parent 8c88504849
commit 2131557669
7 changed files with 34 additions and 2 deletions

View File

@@ -1581,7 +1581,16 @@ pub const Lowering = struct {
var edge_it = edges.iterator();
while (edge_it.next()) |e| {
const fns = module_fns.get(e.key_ptr.*) orelse continue;
if (fns.get(name)) |fd| distinct.put(fd, e.key_ptr.*) catch {};
// Only plain free functions are eligible for rerouting; generic /
// foreign / builtin / #compiler authors keep their existing
// dispatch. Filtering BEFORE the count gate means a same-name
// collision of non-plain authors (e.g. two flat-imported modules
// each `#foreign`ing the same symbol) is NOT counted as ambiguous —
// it falls through to `.none` and the existing first-wins path.
if (fns.get(name)) |fd| {
if (!isPlainFreeFn(fd)) continue;
distinct.put(fd, e.key_ptr.*) catch {};
}
}
if (distinct.count() == 0) return .none;
if (distinct.count() >= 2) return .ambiguous;
@@ -1591,7 +1600,6 @@ pub const Lowering = struct {
const the_one = entry.key_ptr.*;
const the_path = entry.value_ptr.*;
if (winner != null and winner.? == the_one) return .none;
if (!isPlainFreeFn(the_one)) return .none;
return .{ .func = .{ .fid = self.bareAuthorFuncId(the_one, name, the_path), .decl = the_one } };
}