wcc: checker-seam drain — spreads, tuple aliases, yield scoping

Four seams from one review cluster, all landing on the same checker
files; gates ran on the union (rule 11 body).

?-subset: the wwstage walk compared `...spread` ALIAS nodes on both
sides of the error-subset check, falsely rejecting a spread-carried
error return (`(i64 | ...errs)`, cs-accept/ww-reject) — both sides
now flatten like trycountvariants (cstage Tparams are pre-flattened
at type level).

Multi-let/multi-assign: the tuple gates keyed on the RAW rhs kind,
rejecting a NAMED tuple alias (`type pair = (i64,i64)`; cs clean-
reject, ww asserttyped stop) — both stages chase per #99 alias
transparency, wwstage rettupleof peels the alias so cgmassign keeps
the str element's len/cap stores, and the catA massign-alias error
pin re-rules to a run fixture. The N_MLET diagnostic also printed
its operands swapped (elem/declared reversed vs its wording).

Yield: match_yield_type didn't descend into N_SWITCH, so a yield
inside a switch arm typed the match void and dropped the value
(both stages); and a stray yield outside any match arm reached cgen
unchecked — both stages now gate on a match-arm counter (the
c->loops discipline).
This commit is contained in:
2026-08-09 01:51:39 +09:00
parent 503d1ab01e
commit 411515a83b
10 changed files with 207 additions and 39 deletions

View File

@@ -181,6 +181,14 @@ fn rettupleof(c: *cgen, rhs: *syntax.node) *syntax.node = {
if (cnm.len == 0) { return nil; };
let rtyp: *syntax.node = fnretlookupmod(c, cnm, cmod);
if (rtyp == nil) { return nil; };
// #99 alias transparency: a NAMED tuple alias return (`fn f()
// pair`) destructures like its base — peel to the N_TTUPLE (the
// nodetuplearg alias-peel; without it the element walk saw no
// tuple and the str len/cap stores were dropped).
for (rtyp != nil && rtyp.kind == syntax.nkind.N_TNAME) {
rtyp = aliaslookup(c, rtyp.str);
};
if (rtyp == nil) { return nil; };
if (rtyp.kind != syntax.nkind.N_TTUPLE) { return nil; };
return rtyp;
};