wcc/ww: &fn synthesis prefers the current module's fn

The address-of-fn synthesis used a bare lookup — import order could
bind a same-leaf fn from another module, silently LEAQ-ing the wrong
function into a fn-ptr slot. Prefer the current module (mirror
check.c:410/1305). Report item #4 (loud and silent faces pinned).
This commit is contained in:
2026-06-13 03:01:31 +09:00
parent 63e837e820
commit 51e3b8f134
5 changed files with 219 additions and 6 deletions

View File

@@ -13130,7 +13130,12 @@ fn unoptype(c: *checker, e: *node) *node = {
// (cmd/wcc/check.c:668), so `&fn` is `*fn` natively.
if (e.lhs != nil) {
if (e.lhs.kind == nkind.N_IDENT) {
let fs: *sym = scopelookup(c.cur, e.lhs.str);
// #4: curmod preference. A bare `&handler` whose leaf
// also names a fn in a LATER module otherwise binds
// the foreign signature (scopedefineinmodule prepends);
// cstage types a fn ident via scope_lookup_prefer with
// cur_mod (cmd/wcc/check.c:1305).
let fs: *sym = scopelookupprefer(c.cur, c.curmod, e.lhs.str);
if (fs != nil) {
if (fs.skind == skind.SK_FN) {
if (fs.decl != nil) {
@@ -14635,7 +14640,13 @@ fn assignableaddrfn(c: *checker, dst: *node, rhs: *node) bool = {
let id: *node = rhs.lhs;
if (id == nil) { return false; };
if (id.kind != nkind.N_IDENT) { return false; };
let s: *sym = scopelookup(c.cur, id.str);
// #4: curmod preference. Without it a `&handler` whose leaf also
// names a fn in a later module misbinds the foreign fn's signature
// here (scopedefineinmodule prepends → chain-first = last module),
// silently admitting a *fn into a foreign-sig slot or rejecting a
// valid same-module &fn. cstage uses scope_lookup_prefer with
// cur_mod (cmd/wcc/check.c:410, assignable_addrfn).
let s: *sym = scopelookupprefer(c.cur, c.curmod, id.str);
if (s == nil) { return false; };
if (s.skind != skind.SK_FN) { return false; };
if (s.decl == nil) { return false; };