wcc/ww: exprtypeoftry prefers the current module's symbol

The try-operand resolution used bare lookups (ident + bare-leaf call);
a cross-module same-leaf collision mistyped the operand. Prefer the
current module. The historic 995 byte-id break attributed to this swap
was contamination from the guard-bug-carrying bundle — re-probed clean
in isolation and at the full stack. The N_DOT module-keyed leaf stays
task #51. Report item [11], lookup half.
This commit is contained in:
2026-06-13 03:04:52 +09:00
parent 51e3b8f134
commit 1f2bc7fc26
5 changed files with 237 additions and 36 deletions

View File

@@ -16307,14 +16307,13 @@ fn checkisas(c: *checker, n: *node) void = {
fn exprtypeoftry(c: *checker, e: *node) *node = {
if (e == nil) { return nil; };
if (e.kind == nkind.N_IDENT) {
// #11a/task #50: this bare-leaf lookup wants curmod preference
// (scopelookupprefer, the #53/#55 family) but the swap BROKE the
// 995 self-rebuild byte-id — in the bundled self-compile ww's
// scopelookupprefer diverges from cstage's resolution (the same
// curmod-in-bundle layer that blocked #5), flipping a try-operand
// stamp in the selfhost source. Held at plain scopelookup until #50
// lands the bundle curmod fix; aligning here in isolation is unsound.
let s: *sym = scopelookup(c.cur, e.str);
// #11a: curmod preference (the #53/#55 family). A bare ident
// whose leaf also names a global in a later module otherwise
// binds the foreign decl's type, mis-typing the try operand and
// either spuriously rejecting valid `?` code or skipping the F8
// reject. Mirrors exprtype's own N_IDENT arm (scopelookupprefer
// at :2897); cstage types the operand via cexpr with cur_mod.
let s: *sym = scopelookupprefer(c.cur, c.curmod, e.str);
if (s == nil) { return nil; };
if (s.decl == nil) { return nil; };
return s.decl.lhs;
@@ -16335,10 +16334,14 @@ fn exprtypeoftry(c: *checker, e: *node) *node = {
// returns nil below) rides task #51 with the fn-ptr-callee desugar.
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
if (nm.len == 0) { return nil; };
// #11a/task #50: curmod preference wanted here too, held at plain
// scopelookup — the prefer swap broke 995 byte-id (bundle curmod
// divergence, same as the N_IDENT arm above + #5/#50).
let s: *sym = scopelookup(c.cur, nm);
// #11a: curmod preference for the bare-leaf callee. A same-leaf
// `op()?` declared in a later module otherwise binds the foreign
// op's return type — its error subset then spuriously fails (or
// wrongly passes) the enclosing-return check. Mirrors exprtype's
// N_CALL arm (scopelookupprefer at :3336). The N_DOT-callee leaf
// (callee.str above) still resolves bare-leaf, not via the module
// qualifier callee.lhs.str — that module-keyed fix rides task #51.
let s: *sym = scopelookupprefer(c.cur, c.curmod, nm);
if (s == nil) { return nil; };
if (s.skind != skind.SK_FN) { return nil; };
if (s.decl == nil) { return nil; };

View File

@@ -5867,14 +5867,13 @@ fn checkisas(c: *checker, n: *node) void = {
fn exprtypeoftry(c: *checker, e: *node) *node = {
if (e == nil) { return nil; };
if (e.kind == nkind.N_IDENT) {
// #11a/task #50: this bare-leaf lookup wants curmod preference
// (scopelookupprefer, the #53/#55 family) but the swap BROKE the
// 995 self-rebuild byte-id — in the bundled self-compile ww's
// scopelookupprefer diverges from cstage's resolution (the same
// curmod-in-bundle layer that blocked #5), flipping a try-operand
// stamp in the selfhost source. Held at plain scopelookup until #50
// lands the bundle curmod fix; aligning here in isolation is unsound.
let s: *sym = scopelookup(c.cur, e.str);
// #11a: curmod preference (the #53/#55 family). A bare ident
// whose leaf also names a global in a later module otherwise
// binds the foreign decl's type, mis-typing the try operand and
// either spuriously rejecting valid `?` code or skipping the F8
// reject. Mirrors exprtype's own N_IDENT arm (scopelookupprefer
// at :2897); cstage types the operand via cexpr with cur_mod.
let s: *sym = scopelookupprefer(c.cur, c.curmod, e.str);
if (s == nil) { return nil; };
if (s.decl == nil) { return nil; };
return s.decl.lhs;
@@ -5895,10 +5894,14 @@ fn exprtypeoftry(c: *checker, e: *node) *node = {
// returns nil below) rides task #51 with the fn-ptr-callee desugar.
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
if (nm.len == 0) { return nil; };
// #11a/task #50: curmod preference wanted here too, held at plain
// scopelookup — the prefer swap broke 995 byte-id (bundle curmod
// divergence, same as the N_IDENT arm above + #5/#50).
let s: *sym = scopelookup(c.cur, nm);
// #11a: curmod preference for the bare-leaf callee. A same-leaf
// `op()?` declared in a later module otherwise binds the foreign
// op's return type — its error subset then spuriously fails (or
// wrongly passes) the enclosing-return check. Mirrors exprtype's
// N_CALL arm (scopelookupprefer at :3336). The N_DOT-callee leaf
// (callee.str above) still resolves bare-leaf, not via the module
// qualifier callee.lhs.str — that module-keyed fix rides task #51.
let s: *sym = scopelookupprefer(c.cur, c.curmod, nm);
if (s == nil) { return nil; };
if (s.skind != skind.SK_FN) { return nil; };
if (s.decl == nil) { return nil; };

View File

@@ -16307,14 +16307,13 @@ fn checkisas(c: *checker, n: *node) void = {
fn exprtypeoftry(c: *checker, e: *node) *node = {
if (e == nil) { return nil; };
if (e.kind == nkind.N_IDENT) {
// #11a/task #50: this bare-leaf lookup wants curmod preference
// (scopelookupprefer, the #53/#55 family) but the swap BROKE the
// 995 self-rebuild byte-id — in the bundled self-compile ww's
// scopelookupprefer diverges from cstage's resolution (the same
// curmod-in-bundle layer that blocked #5), flipping a try-operand
// stamp in the selfhost source. Held at plain scopelookup until #50
// lands the bundle curmod fix; aligning here in isolation is unsound.
let s: *sym = scopelookup(c.cur, e.str);
// #11a: curmod preference (the #53/#55 family). A bare ident
// whose leaf also names a global in a later module otherwise
// binds the foreign decl's type, mis-typing the try operand and
// either spuriously rejecting valid `?` code or skipping the F8
// reject. Mirrors exprtype's own N_IDENT arm (scopelookupprefer
// at :2897); cstage types the operand via cexpr with cur_mod.
let s: *sym = scopelookupprefer(c.cur, c.curmod, e.str);
if (s == nil) { return nil; };
if (s.decl == nil) { return nil; };
return s.decl.lhs;
@@ -16335,10 +16334,14 @@ fn exprtypeoftry(c: *checker, e: *node) *node = {
// returns nil below) rides task #51 with the fn-ptr-callee desugar.
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
if (nm.len == 0) { return nil; };
// #11a/task #50: curmod preference wanted here too, held at plain
// scopelookup — the prefer swap broke 995 byte-id (bundle curmod
// divergence, same as the N_IDENT arm above + #5/#50).
let s: *sym = scopelookup(c.cur, nm);
// #11a: curmod preference for the bare-leaf callee. A same-leaf
// `op()?` declared in a later module otherwise binds the foreign
// op's return type — its error subset then spuriously fails (or
// wrongly passes) the enclosing-return check. Mirrors exprtype's
// N_CALL arm (scopelookupprefer at :3336). The N_DOT-callee leaf
// (callee.str above) still resolves bare-leaf, not via the module
// qualifier callee.lhs.str — that module-keyed fix rides task #51.
let s: *sym = scopelookupprefer(c.cur, c.curmod, nm);
if (s == nil) { return nil; };
if (s.skind != skind.SK_FN) { return nil; };
if (s.decl == nil) { return nil; };