wcc/ww: tagged-union normalization at tinfofornode (never-drop, dedup, collapse, nullable fold)
wwstage computed tagged sizes/tags off the raw variant list — size() folded wrong constants (size((*u8|void)) 16 vs 8, (i32|never) 16 vs 4) and duplicate variants got divergent tag numbering vs cstage, while ww's own cgen layout folded nullable but its size() didn't. Make tinfofornode's N_TTAGGED arm the normalization SSoT mirroring cstage resolve_type (check.c:801-882): never-drop, duplicate dedup via structural typeeq, single-variant collapse, nullable fold on the normalized pair; astsize/astalign delegate, and voidvariantindex reads the normalized ti.params (cgen.c:900-911) so construct/match/void tag readers agree. Corpus-neutral (zero-move on all combineds); 989_tagnorm_run pins the folds dual-stage, red-proven. Review items #1/#3; residual #45 filed (AST-keyed nullable gate at global emit).
This commit is contained in:
@@ -2967,18 +2967,32 @@ export fn nullableptrtag(t: *node) i32 = {
|
||||
};
|
||||
|
||||
// voidvariantindex — find the 0-based index of the `void` variant in a
|
||||
// tagged-union type expr, -1 if absent. Used by cgreturn to map bare
|
||||
// `return;` in a tagged-union-returning fn to the void variant's tag.
|
||||
// tagged-union type, -1 if absent. Used by cgreturn to map bare `return;`
|
||||
// in a tagged-union-returning fn to the void variant's tag.
|
||||
//
|
||||
// #1/#3 (F1 fold): reads the NORMALIZED variant chain (ti.params, which
|
||||
// tinfofornode now never-drops + dedups), NOT the raw AST tagged.list. The
|
||||
// construct/match tag numbering already rides ti.params, so once F1 dedups
|
||||
// it, a deduped union with a void variant (e.g. `(i32|i32|void)`) would
|
||||
// desync its bare-`return;` void tag from match's if this stayed AST-keyed.
|
||||
// Mirrors cstage cg_tag_for_variant(rt, ty_void) (cmd/w6c/cgen.c:900-911):
|
||||
// chase NAMED, scan params, match bare TY_VOID (not `!void`, carried by the
|
||||
// tparam iserror flag).
|
||||
fn voidvariantindex(tagged: *node) i32 = {
|
||||
if (tagged == nil) { return -1; };
|
||||
if (tagged.kind != nkind.N_TTAGGED) { return -1; };
|
||||
let v: *node = tagged.list;
|
||||
let ti: *tinfo = tagged.type_: *tinfo;
|
||||
if (ti == nil) { return -1; };
|
||||
ti = tichase(ti);
|
||||
if (ti == nil) { return -1; };
|
||||
if (ti.kind != tykind.TY_TAGGED) { return -1; };
|
||||
let p: *tparam = ti.params;
|
||||
let idx: i32 = 0;
|
||||
for (v != nil) {
|
||||
if (v.kind == nkind.N_TNAME) {
|
||||
if (streq(v.str, "void")) { return idx; };
|
||||
for (p != nil) {
|
||||
let vt: *tinfo = p.type_;
|
||||
if (vt != nil && vt.kind == tykind.TY_VOID && !p.iserror) {
|
||||
return idx;
|
||||
};
|
||||
v = v.next;
|
||||
p = p.tnext;
|
||||
idx += 1;
|
||||
};
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user