pushargsrev's five aistagged gates (N_IDENT #55, N_CALL #21, N_INDEX #12, N_DOT #22a, deref #35) treated a tagged arg as already-tagged when its SLOT SIZE matched the param's. A same-slot subset union ((bool|void) into (i64|bool|void), both 16B) then natural-pushed the narrower box's words carrying SOURCE tags — no re-layout, no cg_widen_tag_remap twin — so the callee matched the wrong arm (silent: probes exited 10/90 where cstage exits 30/27). cstage keys widen detection on type equality (cgen.c:10000 same = (pu == au) || type_eq) and routes every non-same tagged source through the zeroed scratch + tag remap; the slot-DIFFER wwstage path already mirrored that byte-identically, so the fix computes cstage's same check once (wsame) and replaces each slot-size test with it. This also erases the last known cs!=ww shape divergence (the 16B-local staging vs direct-push frame delta on prefix subsets). 8 subsetwiden_* fixtures own the class: call-result/ident/str-payload /mid-arg remap (the wrong-arm shapes), prefix (the shape-divergence repro), and bigslot/return-pos/struct-24-to-32 sibling guards. Corpus pin 1740/343/22/209/1166/3480.
14 lines
254 B
Plaintext
14 lines
254 B
Plaintext
//ww:run-exit 30
|
|
package main;
|
|
fn pick(r: (i64 | bool | void)) i32 = {
|
|
match (r) {
|
|
case let n: i64 => return 10;
|
|
case let b: bool => return 30;
|
|
case void => return 20;
|
|
};
|
|
};
|
|
export fn main() i32 = {
|
|
let v: (bool | void) = true;
|
|
return pick(v);
|
|
};
|