wcc: #99 alias-of-tuple — chase TY_NAMED in tuple coercion (cstage) + param spill (wwstage)

type pair = (int, int); let x: pair = (3, 4) -- an alias of a tuple
initialized from an untyped literal, and passing such a value to a fn --
was a both-stage bug, mirror-twins of the same TY_NAMED-not-chased root:

cstage CHECKER over-rejected the init (not assignable to declared pair):
type.c's tuple-assignable arm gated on the un-chased dst kind, so a
TY_NAMED alias skipped the per-element untyped->int coercion the direct
tuple path applies. Fix: chase TY_NAMED both sides (mirrors the #258
slice-borrow arm). Direct and typed-alias tuples already worked; only
alias+untyped was rejected.

wwstage CGEN dropped the second word of an alias-tuple fn-arg: the
tuple-param spill at cgendecl.ww gated on the syntactic N_TTUPLE, so an
alias param (N_TNAME) fell to the scalar path and spilled one slot ->
t.1 read frame garbage. Fix: chase the alias via aliaslookup to the
resolved N_TTUPLE and spill all its slots. cstage cgen was already
correct -- the bug was checker-only there. Converges cs==ww byte-id.

One commit: same construct, the two halves must ship together (either
alone leaves cs!=ww). test/wcc/826 (init/fn-arg/return, 2-field byte-id);
test/wcc/944 4 rows graduated err->run-correct. byte-id 990-997 8/8.
This commit is contained in:
2026-06-08 23:12:06 +09:00
parent fca979470f
commit 83025b03a6
7 changed files with 458 additions and 53 deletions

View File

@@ -50,23 +50,14 @@
* | R4-blessed train; #100's ww twin |
* | chase closed the window — LOUD-HOLD |
* | pair, twin texts share the experr | err/err
* tuparg_bound99 / | kb5_tuparg(1): literal named-tuple |
* tuparg1_bound99 | arg — cs checker-rejects (#86-kin), |
* | WW RUNS WRONG exit 1 (task #99, |
* | metric-1 ww side). Dual-cell pin | err/1
* tuparg_cast_bound99 | kb5_tuparg_c: cast spelling dodges |
* | the cs checker; the :249 chase made |
* | cs run CORRECT (LIVE c1 graduation, |
* | C1-CORR-3 — corrects rob R3 + ken |
* | FLAG-2); ww still WRONG exit 1 |
* | (#99). Two-key pin: cs-0 earned + |
* | ww-1 pinned-wrong; byte-id waived |
* | until #99 re-pins to full byte-id | 0/1
* tupglobal_bound86 | kb5_tupglobal: alias-tuple global — |
* | cs checker-dead (#86), ww runs 0. |
* | #85 type_unwrap close is SITE- |
* | closure with zero live graduations |
* | — this row pins the bound | err/0
* tuparg_bound99 / | alias-tuple fn-arg (2-lvl / 1-lvl |
* tuparg1_bound99 / | / cast spelling) + alias-tuple |
* tuparg_cast_bound99/| global. #99 GRADUATED: cstage |
* tupglobal_bound99 | type.c chase accepts the coercion, |
* | wwstage cgendecl.ww spill chase |
* | sizes the alias param 16B (was |
* | dropping SI → t.1 garbage). All |
* | now 0/0 byte-id | 0/0
* ---- c2 (#73 graduation: tripwire deleted, 6 fu gates chased) --
* g73_idxstore / | slice / str / tagged 2-lvl alias |
* g73_strfield / | field at the indexed-elem STORE |
@@ -365,10 +356,12 @@ static const struct row rows[] = {
" return 0;\n"
"};\n", 0, 0, K_BUILDERR,
"has a str/slice/struct/tagged element" },
/* node_tuplearg:249 pin (ken FLAG-2): the LITERAL spelling has
* NO GREEN TARGET — cs checker-rejects even at 1 level (#86-kin)
* while WW ACCEPTS AND RUNS WRONG (exit 1, task #99 metric-1
* ww-side). Cells pinned as observed. */
/* #99 GRADUATION: both halves landed — the cstage type.c
* type_chase_named tuple-arm (init/fn-arg untyped->alias coercion
* reject->accept) AND the wwstage cgendecl.ww tuple-PARAM spill
* chase (alias param fell to the scalar path, dropped SI, t.1
* garbage). All four rows now build+run 0 on BOTH stages and the
* .s is byte-identical (full 0/0 byte-id, the designed path). */
{ "tuparg_bound99",
"package main;\n"
"type tp0 = (i64, i64);\n"
@@ -378,8 +371,7 @@ static const struct row rows[] = {
" let t: tp = (4, 9);\n"
" if (f(t) != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 1, K_CSERR_WWRUN,
"not assignable" }, /* ww: task #99 */
"};\n", 0, 0, K_RUN, NULL },
{ "tuparg1_bound99", /* 1-LEVEL identical — not alias-depth */
"package main;\n"
"type tp = (i64, i64);\n"
@@ -388,15 +380,10 @@ static const struct row rows[] = {
" let t: tp = (4, 9);\n"
" if (f(t) != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 1, K_CSERR_WWRUN,
"not assignable" }, /* ww: task #99 */
/* C1-CORR-3 (corrects rob R3 + ken FLAG-2): the CAST spelling
* dodges the cs checker, and the :249 chase gave it a LIVE cs
* graduation — cs now classifies the alias-tuple arg and runs
* CORRECT. ww still runs WRONG (#99). Two-key pin: cs-0 earned
* + ww-1 pinned OBSERVED-WRONG; byte-id waived — when #99's ww
* fix lands, the ww cell reds and forces the re-pin to full 0/0
* byte-id (the designed graduation path). */
"};\n", 0, 0, K_RUN, NULL },
/* cast spelling — was the LIVE-cs / wrong-ww K_RUN_NOID pin; the
* wwstage spill chase reds the old ww-1 cell and graduates it to
* full 0/0 byte-id alongside its siblings. */
{ "tuparg_cast_bound99",
"package main;\n"
"type tp0 = (i64, i64);\n"
@@ -406,12 +393,10 @@ static const struct row rows[] = {
" let t: tp = (4, 9): tp;\n"
" if (f(t) != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 1, K_RUN_NOID, NULL }, /* ww+byte-id: task #99 */
/* #85 SITE-closure bound: type_unwrap's consumers (:14716/:14907
* tuple-global layout walks) are checker-DEAD on cs for alias
* tuples (#86 upstream) — the c1 chase graduates NOTHING live
* here; ww runs the global correctly. */
{ "tupglobal_bound86",
"};\n", 0, 0, K_RUN, NULL },
/* alias-tuple module-global — the cstage chase accepts the global
* init and ww already read it correctly; now both 0/0 byte-id. */
{ "tupglobal_bound99",
"package main;\n"
"type tp0 = (i64, i64);\n"
"type tp = tp0;\n"
@@ -419,8 +404,7 @@ static const struct row rows[] = {
"export fn main() i32 = {\n"
" if (G.0 + G.1 != 13) { return 1; };\n"
" return 0;\n"
"};\n", 0, 0, K_CSERR_WWRUN,
"not assignable" }, /* cs: task #86 */
"};\n", 0, 0, K_RUN, NULL },
/* ---- c2: #73 graduation — the F1 tripwire's containment
* replaced by the designed chase (close-by-construction). Each
* row was the loud "#73" fatal on cs at the c1 tip (ww ok/0);