Commit Graph

7 Commits

Author SHA1 Message Date
83025b03a6 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.
2026-06-08 23:12:06 +09:00
1f14becdf3 cgen: B6-c1 assign/reassign family single peels fold into type_chase_named — 9 lines, cs-only
The exact B6-c1 set (rob b6 spec §2): cgexpr :6359 (tagged-local plain
reassign lu), :6403/:6405 (deref-target assign pu/vt), :6460/:6462
(deref compound-assign pu/vt), :6518 (str/slice/struct reassign lu) +
cgstmt :11696 (nomem null-propagate r), :12047 (assign base peel bu),
:13625 (destructure-reassign rhs ru — chased; the #64 citation above it
stays, the deferral is about the tuple-literal rhs ROUTE, not this
peel). Raw `->under` in cgen.c 58→49.

TRAIN INVARIANT: cs-only — zero selfhost/ or lib/ bytes move; w6c_ww/
ww_ww bit-identical to ken's 4cac1cb baselines (md5
b6bddc8eb5c3ed8e805e50371d4b7017 / 4e9ca8741f19e1f68219ff799a5e5a14).
cs movers bounded to exactly: kb6_streassign, kb5_wstore_a (the
named c1 family); the rest of the kb4/kb5/kb6/kna corpus + five
selfhost mains byte-NEUTRAL both stages; kw1_101 / fill2 / tuparg_c /
xampdef / amplen1 detectors unmoved. 989 lib ratchet: zero flips.

LIVE graduation: kb6_streassign (the :6518 lu single-peel missed
TY_STR at 2 alias levels, fell to the scalar default — `b = a` copied
the ptr WORD0 only, len/cap stale, cs silent exit 1; ww was the
runtime-correct full 3-word reference) → 0/0 byte-id. Designed
graduation: kb5_wstore_a (ken C1-CORR-2 seed — the ident-lhs N_ASSIGN
tagged gate :6359 is cgexpr INLINE, never reached B5's :2456 funnel)
→ wstore_a_2lvl re-pinned K_RUN_NOID→K_RUN in the b5 suite (84→85
checks). kb6_sreassign / kb6_dassign latent controls byte-NEUTRAL as
ken's structural bound predicts.

New 944_alias_cgen_b6_run row table (3 rows, 9 checks): streassign_2lvl
+ sreassign_2lvl/dassign_2lvl controls; Makefile wires
test_alias_cgen_b6_run into the unit list. All 944-family suites green;
sizelint 0.
2026-06-06 03:48:54 +09:00
4cac1cbb89 wcc_ww/cgen: W1 #100 struct-lit fill gate keys off the chased stamped tinfo
The ww twin of B5-c1's :3195 cg_structlit_fill chase — closes the
R4-blessed one-train acceptance divergence (cs-loud / ww-SILENT-WRONG
on alias-element array fills, ken FLAG-3 / kb5_fill2). The #249 fill
arm's loud-gate element classification was alias-blind on two of four
keys: a raw N_TSLICE kind test and a structlookup leaf-name probe —
`type el = el0;` matched neither, bypassed the gate, and fell to the
scalar tail (one word per element, silent exit 1, gate-blind #263
class). Now: issliceel via isslicetype (stamped tinfo, the str/tagged
keys' existing route) and isstructel via tichase + TY_STRUCT kind —
the tnodeisagg discipline the neighboring #49 arm already uses, twin
of cstage type_chase_named at cgen.c:3179. NO new helper.

Loudness-alignment only, zero acceptance movement elsewhere: probe
matrix holds direct str/slice/struct/tagged elem LOUD (twin texts),
int/alias-int/f64 elem fills build + run 0/0 byte-id, 1- and 2-level
alias struct/slice/tagged elems now LOUD both stages.

ww-only: cs side untouched (zero C bytes; w6c up-to-date across the
edit). B5 detector rows hold post-B5 expected state (targ/tmem/wpush/
null/succ/f32p/def93 all 0/0 byte-id). 989 ratchet ZERO flips
(31 ID / 9 pinned-divergent / 3 pinned-wwreject). combined.ww regen'd
for both embedded targets (w6c_ww, wwdump).

944_alias_cgen_b5_run: fill2 graduates the dual-cell K_CSERR_WWRUN
pin to the K_BUILDERR LOUD-HOLD pair (fill0-class, shared experr
tail); fill0 control holds. Check count holds at 84/84 — the kind
flip is cell-count-neutral (2 driver cells either side, no byte-id
cell). All 944-family suites green; sizelint 0; test-unit all 291
passed. Closes #100; the R4 divergence window closes with it.
2026-06-06 03:09:54 +09:00
837fdb4753 cgen: B5-c4 #93 deref-index pointee chase — the one spurious MOVQ, #263-polarity
Trace at the c3 tip: cs-vs-ww diff on l2_local/kb5_def93 = exactly ONE
line, a spurious `MOVQ (AX), AX`. The deciding site is the cgexpr
N_UN(STAR) pointee classify (`ru`): the single peel left a 2-LEVEL
alias pointee TY_NAMED, the ARRAY skip (#61-C — an array value IS its
address, #270-1a) missed, and the scalar load pulled a[0]'s VALUE as
the index base — wild pointer, SIGSEGV 139 on cs. KEN #263-POLARITY:
cs is the WRONG side; ww chases and is the runtime-correct reference —
cs converges on WW's asm. Single-site grant: the one `ru` computation
(shared by the FN/ARRAY/TAGGED skip predicates) → type_chase_named.
Raw `->under` in cgen.c 59→58. #93 CLOSES.

TRAIN INVARIANT holds at the tip: cs-only; _ww binaries bit-identical
to the bcd948d baseline md5s across all four commits. cs movers vs the
c3 tip bounded to EXACTLY the deref-index shapes: l2_local, kb4_x93,
kb5_def93. Zero ww movers. Detector pinned: kb4_xampdef STAYS 139/139
(#94, out-of-train — `&D[i]` indexed def base, a different site).

Graduations (cs SEGV-139 / ww 0, BYTE-DIVERGE → 0/0 BYTE-ID):
g93_l2_local (the banked rob spelling), g93_def (kb5_def93, the
natural `(*p)[2]` def twin). g93_1lvl_ctl (1-level control) held 0/0
byte-id throughout.

944_alias_cgen_b5_run 28→31 rows (84 checks); 944 family green;
sizelint 0.
2026-06-06 02:26:29 +09:00
140755d221 cgen: B5-c3 #89 cgreturn return-position widen — rt/vu chase, trace-first
Trace at the c2 tip (rebuilt binaries, #80-c4 form): ret_widen's mk()
emitted `MOVQ -16(BP),AX / MOVQ AX,DX / MOVQ $0,CX` — the scalar
shuffle arm, payload word 1 ZEROED (s.b/e.aux dropped, cs silent
exit 1). Deciding predicate: the vu single peel left an alias struct
source TY_NAMED → isstruct false → scalar arm. The rt single peel was
the succ half: a 2-LEVEL alias return type stayed NAMED → the whole
tagged-return block was skipped → no tag synthesis at any return
(kb5_succ's three paired return-position insertions). Fix = the three
granted peels (bare-return rt, value-return rt, vu) →
type_chase_named; the route predicates (istagged/isstruct/istuple/
passthrough) key on the chased vu. Raw `->under` in cgen.c 62→59.
#89 CLOSES.

TRAIN INVARIANT holds: cs-only; _ww binaries bit-identical to the
bcd948d baseline md5s. cs movers vs the c2 tip bounded to EXACTLY the
return-route family: ret_widen, kb4_xret, kna_ret_errunion, kb5_succ.
Zero ww movers; detectors pinned (kb4_xampdef stays 139/139 #94;
def93/x93/l2_local stay cs-SEGV — c4's targets; fill/tuparg/v2
families unchanged).

Graduations (cs1/ww0 BYTE-DIVERGE → 0/0 BYTE-ID): g89_ret_widen (the
banked spelling), g89_ret_errunion (the live e.aux truncation seed),
and succ_2lvl flips K_RUN_NOID → K_RUN exactly as C1-CORR-1 predicted
(pins-follow-the-layer). g89_ret_named_ctl (bare NAMED control) held
0/0 byte-id throughout.

944_alias_cgen_b5_run 25→28 rows (75 checks); 944 family green;
sizelint 0.
2026-06-06 02:23:18 +09:00
e36af4fe7e cgen: B5-c2 #73 graduation — the 6 tripwired field gates chase, tripwire deleted
Close-by-construction replacing containment — the designed graduation
path from F1-c1's commit body. The 6 fld_alias_tripwire call sites
(indexed-elem field store/read, heap struct-lit field fill, tuple-elem
read, ptr-chain field read, static struct-lit emit) chase their fu
through type_chase_named; the 6 tripwire calls AND the helper itself
(incl. its :447 peel) are DELETED. Raw `->under` in cgen.c 69→62.
#73 CLOSES.

TRAIN INVARIANT holds: cs-only; w6c_ww/ww_ww bit-identical to the
bcd948d baseline md5s (28ad889042bad8006f1997cbcec94805 /
4e9ca8741f19e1f68219ff799a5e5a14). ZERO new corpus movers vs the c1
tip (kb*/kna corpus + five mains byte-NEUTRAL — the chased gates only
fire on 2+-level alias aggregate fields, none in corpus).

Gate-arm graduations (pre = loud "#73" fatal on cs, ww ok/0; post =
0/0 BYTE-ID): slice/str/tagged arms at the indexed STORE gate
(g73_idxstore/g73_strfield/g73_tagfield), slice arm at the indexed
READ / ptr-chain READ / tuple-elem READ gates (g73_idxread/g73_ptrread/
g73_tupread), nested-struct arm at the static emit gate
(g73_static_struct). The existing 944_alias_accept_run tripwire bound
row graduates K_BUILDERR_CS → K_RUN.

Two arms cannot pin the full 0/0 byte-id cell — documented, not silent:
  - heap fill (g73_heapfill, COMPILE-only pin): bare /tmp programs
    never link malloc (both stages, pre-existing infra) and ww's
    deref-field READ carries the #24-kin field(SB) leak; the chased
    FILL bytes verified byte-id by hand against the plain (non-alias)
    control — divergence shape identical, all of it in the pre-existing
    read sites.
  - str-field static emit (g73_static_str): the #73 fatal gave way to
    the pre-existing #129 A.2 foldability loud on cs — now both-loud
    twin texts (fill0 class), pinned as K_BUILDERR.
  - struct-copy arm: NO runnable repro reaches these gates — indexed
    whole-struct field reads take the (already chased, byte-id) address
    spine, and tuple-of-struct louds upstream on BOTH stages (#54-kin
    "aggregate init from unhandled rhs shape"). The arm's only carrier
    was the heap gate, covered by the compile pin above.

944_alias_cgen_b5_run grows 16→25 rows (65 checks); all 944-family
suites green; sizelint 0.
2026-06-06 02:19:39 +09:00
1cc663f494 cgen: B5-c1 helper+funnel single peels fold into type_chase_named — 19 sites, cs-only
The exact F2b c1 set (rob next-arc spec + B5 re-rule): node_tuplearg:249,
fld_issigned:409, castsrcprim:501/:531, struct_float_class:598,
tagged_arg_size:640, tagged_memarg_size:661, type_isnullable:740,
nullable_ptr_tag:750, cg_tagged_success_tag:860, cg_variant_is_error:876,
cg_tag_for_variant:899, type_istagged:953, type_unwrap:1269 + the widen/
fill funnel entries cg_widen_tagged_store:2456/:2480/:2483,
cg_widen_tagged_push:2905, cg_structlit_fill:3195. Raw `->under` in
cgen.c 88→69. Riding per re-rule R1: peel-ok-#218 annotations at
cg_variant_match/cg_variant_struct_match (citing ken's b5 oracle §4 —
chasing those four peels graduates zero v2_struct rows; the real fix is
a both-stage NAMED-source arm, task #95) and the :755 peel-ok annotation
mirroring ww cgenutil.ww:2758 (probe-cleared, 018ef66). :447 untouched
(c2's grant).

TRAIN INVARIANT: cs-only — zero selfhost/ or lib/ bytes move; w6c_ww/
ww_ww/w6a_ww/w6l_ww bit-identical to the bcd948d baselines (md5
28ad889042bad8006f1997cbcec94805 / 4e9ca8741f19e1f68219ff799a5e5a14).
cs movers bounded to exactly: kb5_targ, kb5_tmem, kb5_wpush, kb5_null,
kb5_f32p, kb5_fill2, kb5_tuparg_c; five selfhost mains + the rest of the
kb2/kb3/kb4/kb5/kna corpus byte-NEUTRAL both stages.

LIVE graduations: kb5_targ (tagged_arg_size sized a 2-level alias union
param 0 → wrong arg path, cs silent exit 1) and kb5_tmem (>48B memarg
twin) → 0/0 byte-id. Divergence flips to byte-id: wpush/null/f32p.

#85 CLOSES as SITE-CLOSURE with ZERO live graduations: type_unwrap's
two consumers (:14716/:14907, both tuple-global layout walks that want
the chased view) are checker-DEAD on cs for alias tuples (#86 upstream)
— correctness there is by-construction, pinned by tupglobal_bound86.

DESIGNED DIVERGENCE (re-rule R4, task #100): the :3195 chase flips
kb5_fill2 from both-wrong-IDENTICAL-silent (gate-blind, both stages
accepted and ran wrong byte-identically) to cs-LOUD / ww-silent-wrong.
A loud, disclosed, pinned divergence over a silent miscompile; rejected
programs emit no asm so the byte-id gates hold. Dual-cell pin
(fill2_bound100): cs experr + ww run-exit-1 both asserted; fill0
both-loud control holds. #100 (the ww twin gate) fires immediately
after B5 so the window is one train wide.

Oracle corrections at the c1 boundary (ken c1-BOUNDARY ADDENDUM,
verified on his independent scratch build; rob ack'd, scope unchanged):
  C1-CORR-1: kb5_succ does NOT flip here — its residual divergence is
  exactly three paired return-position tag syntheses, the cgreturn
  return-route family (:12278/:12318/:12322). Joins c3's graduation
  set; pinned succ_bound_c3 K_RUN_NOID until then.
  C1-CORR-2 (corrects re-rule R2): kb5_wstore_a does NOT flip — the
  ident-lhs N_ASSIGN tagged store gates in the cgexpr INLINE set (B6),
  never reaching the :2456 funnel; cs byte-neutral here. Pinned
  wstore_a_bound_b6 K_RUN_NOID; byte-id rides B6.
  C1-CORR-3 (corrects re-rule R3 + ken FLAG-2): the :249 chase is NOT
  purely latent — the CAST spelling (kb5_tuparg_c) earned a LIVE cs
  graduation (cs ok/1 → ok/0, correct tuple-arg classify); ww still
  runs wrong (task #99). Two-key pin tuparg_cast_bound99: cs-0 earned +
  ww-1 pinned observed-wrong; byte-id re-pins to full 0/0 when #99's ww
  fix lands.

New 944_alias_cgen_b5_run row table (16 rows, 40 checks): controls
signed/wstore/wstore1 byte-NEUTRAL as predicted (kind-keyed tests are
the only behavior-visible peels — type.c classifiers already recurse);
literal tuparg spellings stay dual-cell bounds (#99/#86). All 944-family
suites green; sizelint 0.
2026-06-06 02:15:14 +09:00