selfhost/cmd/wcc/check: same-module preference on N_IDENT callee lookup
exprtype's N_CALL callee resolution used flat scopelookup, returning the first match in the bucket regardless of caller module. Two modules exporting fns with the same leaf name (e.g. alpha.foo i64 + beta.foo str) caused bare-leaf callees inside one of them to pick the other's fn, then false-positive at return type. Cstage cexpr N_IDENT routes through scope_lookup_prefer(c->cur, c->cur_mod, name) which short-circuits to the same-module hit before falling through to flat scope. Mirror at check.ww:675 — splits N_IDENT vs N_DOT so the latter keeps flat scopelookup and the explicit module qualifier path stays distinct (tracked as #58). c.curmod is already tracked by checkfile pass 2 (check.ww:1240-1241), so this is a one-call swap on the N_IDENT branch. No plumbing. Reviewer cascade probe across all 131 .ww/.combined.ww files in lib/ + selfhost/ shows lib/memio/memiotest.combined.ww drops 4 spurious "let: not assignable" lines as a side effect, with no new errors. Net improvement.
This commit is contained in:
@@ -7666,7 +7666,20 @@ fn exprtype(c: *checker, e: *node) *node = {
|
||||
if (callee.kind == nkind.N_IDENT) { nm = callee.str; };
|
||||
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
|
||||
if (nm.len == 0) { return nil; };
|
||||
let s: *sym = scopelookup(c.cur, nm);
|
||||
// #56: bare-leaf N_IDENT calls go through scopelookupprefer so
|
||||
// `foo()` inside module M binds to M.foo rather than another
|
||||
// module's same-leaf foo at the head of the flat scope bucket.
|
||||
// Mirrors cstage cexpr N_IDENT routing through
|
||||
// scope_lookup_prefer with c->cur_mod. N_DOT keeps the bare
|
||||
// scopelookup — its module-qualified resolution is a separate
|
||||
// gap (parser stores the leaf in callee.str; mod is in
|
||||
// callee.lhs.str, not consumed here yet).
|
||||
let s: *sym = nil;
|
||||
if (callee.kind == nkind.N_IDENT) {
|
||||
s = scopelookupprefer(c.cur, c.curmod, nm);
|
||||
} else {
|
||||
s = scopelookup(c.cur, nm);
|
||||
};
|
||||
if (s == nil) { return nil; };
|
||||
if (s.skind != skind.SK_FN) { return nil; };
|
||||
if (s.decl == nil) { return nil; };
|
||||
|
||||
@@ -672,7 +672,20 @@ fn exprtype(c: *checker, e: *node) *node = {
|
||||
if (callee.kind == nkind.N_IDENT) { nm = callee.str; };
|
||||
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
|
||||
if (nm.len == 0) { return nil; };
|
||||
let s: *sym = scopelookup(c.cur, nm);
|
||||
// #56: bare-leaf N_IDENT calls go through scopelookupprefer so
|
||||
// `foo()` inside module M binds to M.foo rather than another
|
||||
// module's same-leaf foo at the head of the flat scope bucket.
|
||||
// Mirrors cstage cexpr N_IDENT routing through
|
||||
// scope_lookup_prefer with c->cur_mod. N_DOT keeps the bare
|
||||
// scopelookup — its module-qualified resolution is a separate
|
||||
// gap (parser stores the leaf in callee.str; mod is in
|
||||
// callee.lhs.str, not consumed here yet).
|
||||
let s: *sym = nil;
|
||||
if (callee.kind == nkind.N_IDENT) {
|
||||
s = scopelookupprefer(c.cur, c.curmod, nm);
|
||||
} else {
|
||||
s = scopelookup(c.cur, nm);
|
||||
};
|
||||
if (s == nil) { return nil; };
|
||||
if (s.skind != skind.SK_FN) { return nil; };
|
||||
if (s.decl == nil) { return nil; };
|
||||
|
||||
@@ -7666,7 +7666,20 @@ fn exprtype(c: *checker, e: *node) *node = {
|
||||
if (callee.kind == nkind.N_IDENT) { nm = callee.str; };
|
||||
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
|
||||
if (nm.len == 0) { return nil; };
|
||||
let s: *sym = scopelookup(c.cur, nm);
|
||||
// #56: bare-leaf N_IDENT calls go through scopelookupprefer so
|
||||
// `foo()` inside module M binds to M.foo rather than another
|
||||
// module's same-leaf foo at the head of the flat scope bucket.
|
||||
// Mirrors cstage cexpr N_IDENT routing through
|
||||
// scope_lookup_prefer with c->cur_mod. N_DOT keeps the bare
|
||||
// scopelookup — its module-qualified resolution is a separate
|
||||
// gap (parser stores the leaf in callee.str; mod is in
|
||||
// callee.lhs.str, not consumed here yet).
|
||||
let s: *sym = nil;
|
||||
if (callee.kind == nkind.N_IDENT) {
|
||||
s = scopelookupprefer(c.cur, c.curmod, nm);
|
||||
} else {
|
||||
s = scopelookup(c.cur, nm);
|
||||
};
|
||||
if (s == nil) { return nil; };
|
||||
if (s.skind != skind.SK_FN) { return nil; };
|
||||
if (s.decl == nil) { return nil; };
|
||||
|
||||
Reference in New Issue
Block a user