176904dffcc9957d3a4f1e816f3d869758afd94d
The outer widen of a NAMED multi-variant union value into an enclosing union mis-tagged: the store took the tagged-subset path (inner value at slot+0 plus a sub-variant remap, collapsing every inner sub-variant onto outer tag 0), while the match-extract reads the nested layout (outer tag at +0, inner 16B value at +8). Store and extract disagreed, so the match selected the first arm. Pre-existing silent miscompile, latent because error-origination sites (`let e: io.error = <leaf>; return e`) were gate-blind — no test discriminated a freshly-originated error at a branched caller; the io vstream surface is the first to do so. Fix, both stages, byte-identical: cg_variant_match (cmd/w6c/cgen.c) and its wwstage mirror cgvariantmatch (cgenutil.ww) fall back to structural equality of the unwrapped tagged unions when the alias collapse loses nominal identity (a NAMED outer variant vs an unwrapped-tagged source); the widen store now writes the inner value at slot+8 and the outer tag at +0, matching the extract. The inner union's build/payload/extract already worked (a destructure through the outer round-trip recovers the inner payload) — only the outer-widen store was wrong. Collision guard (the fallback is unsound without it): structural matching cannot disambiguate two nominally-distinct same-shape variants in one outer union. That is unreachable under today's nominal-lossy collapse but inverts the moment #199b lands the nominal layer, so if >=2 outer variants structurally match the source we hard-error at compile time citing #199b — both stages, an enforced invariant rather than a "rare, trust it" assumption. Folds #219: the wwstage tinfo typeeq (lib/ww/typ.ww) had no TY_TAGGED branch and fell through to `return true` (any two tagged unions compared equal); cstage type_eq (type.c:269) has the structural branch. The structural fallback above is the first and only caller to compare two bare tagged unions, so #219 is unexercised — and therefore ungateable — in isolation; it folds here per the rule-11 couldn't-split carve-out (same structural reason as #206's N_TTUPLE fold). The added branch mirrors cstage type_eq, tightening wwstage into alignment. test/wcc/925_nested_union_widen_run: outer-arm select, destructure-after- propagation (payload survives the round-trip), destructure-let, single-variant control, and the collision-guard compile-error, each with a cstage==wwstage byte-id check (the path is gate-blind). Interim until #199b/B-full lands the true nominal wrapped-slot layout.
Description
No description provided
Languages
C
89.4%
Python
7.2%
Makefile
2.3%
Shell
0.8%
Assembly
0.3%