Hojun-Cho b787641ef9 selfhost+test: route N_DOT match scrutinee through fnretlookupmod (#31)
Wwstage matchscrutt now mirrors cstage's typed-AST scrutinee-type
lookup for module-qualified mod.fn(...) callees, restoring per-arm
tag dispatch on cross-module shadowed-name 4-arm matches. Class A
runtime miscompile, silent across collectfnrets shadowing — was
the 8th unmask of session 5.

Pre-fix: wwstage's matchscrutt N_DOT branch (cgenutil.ww:2061)
called `fnretlookup(c, callee.str)` — name-only resolution.
collectfnrets prepends to c.fnrets, so when a caller fn (e.g.
lib/strings's `next`) shadows a callee fn-name (utf8's `next`),
the prepend chain has the caller's narrower tagged return at the
head. matchscrutt then resolved the scrutinee type to the WRONG
tagged shape, and variantindex lookups for arms past the
shadowing caller's variant count returned -1 → want=0 →
match-arm `CMPQ $0, AX` for arms 2 and 3 on a (rune | done |
more | invalid) probe. Effect: arms 2/3 silently unreachable
even when the runtime tag matched, falling through to default.

Cstage gets the scrutinee type via the checker-set callee type
on the N_DOT node, so picks the correct utf8.next return shape.

Polarity catalog: wwstage UNDER — fnretlookup missing module-
preferring discipline. **Third leaf in the same trio**: #27
(aliaslookupmod), #28 (fnparamslookupmod), #31 (fnretlookupmod).
Pattern is recurring; full graduation of all leaf-name lookups
to same-module-first is a candidate for STATUS-3 task #1
variant-widen consolidation refactor (deferred to next session
opener per rob).

Fix: new fnretlookupmod helper in cgen.ww (same-module-first
walk, fallback to existing first-match — cell-for-cell mirror
of fnparamslookupmod from #28). matchscrutt N_DOT branch
extracts `cmod` from callee.lhs.str and routes through the
helper. Other 13 fnretlookup callsites untouched per #28's
"fix only what has a real consumer" discipline. fnret.fmod
field + collectfnrets f.fmod assignment already landed in #28.

Surfaced by lib/strings commit-2 pre-flight: probe iter+next
shape calls utf8.next; the probe's own `fn next` shadows
utf8.next at the c.fnrets head. Bootstrap-stable because no
selfhost-corpus path shadows a fn name across modules with a
wider tagged return on the shadowed side; lib/strings.iter
pulling utf8.next under wwstage was the first exerciser.

Filed follow-up (NOT in scope here): #32 wwstage runtime stomp
on utf8.next via *iterator caller — separate Class A surfaced
by 929 direct utf8.next regression row design. #31's fix is
correct in isolation; #32 blocks lib/strings commit 2 (#30).

Tests:
  - 728_match_4arm_cross_module pins distinct CMPQ $K, AX tags
    in TEXT b.next via bitmap covering [0..arms), robust to
    arm ordering. Three cross-module shadowed-name shapes × cmp
    -s byte-id. Sentinel-flip-verified: revert fnretlookupmod
    route → 3/6 wwstage fixtures fail "arm K repeats tag $0
    (collapse)".
  - 929_match_4arm_cross_module_run runtime-pins 6 rows × 2
    stages per-arm exit-code shape: 3/4/5/6-arm boundary,
    mixed (i32|str|rune|u8), reverse arm-order in match source.
    Confirms bug follows fnretlookup-resolved type, not match
    source order.

102/102 ok. 995_self_rebuild stays green (ww2==ww3==ww4 byte-id).
2026-05-18 11:12:14 +09:00
2026-05-10 01:24:58 +09:00
Description
No description provided
12 MiB
Languages
C 89.4%
Python 7.2%
Makefile 2.3%
Shell 0.8%
Assembly 0.3%