selfhost/cmd/wcc: type-key tagged variant match (#66, Phase-N step 3)
The user-ruled B-full semantic change: flip tagged-union variant matching from surface-NAME to TYPE-identity (typeeq over tinfo.params), mirroring cstage cg_variant_match (cmd/w6c/cgen.c:451). A cross-module `a.T` != `b.T` and `type linerr=!str` != str are now distinguished by the per-decl TY_NAMED pointer (Phase-N #64). ww has no type_assignable, so the untyped/loose arm keeps the str/slice shape fallback (rule-10 align-down). The 5 helpers (flatvariantidx, flatslicevariantidx, taggedvariantindex, cgtagvariantidx, cgmatch dispatch) flip; nomem propagation (NAMED-name scan, no source value) and the f64 widen arm (float-kind classification, no pattern node) are not arm-by-value discrimination and stay name/kind-keyed. The flip requires value nodes to carry nominal identity. exprtype's N_STRUCTLIT arm stamped the flattened body, so `overflow{}` (overflow=!void) got TY_VOID and missed its variant -- fixed to stamp the per-decl NAMED (mktname(lhs.str) -> tinfofornode reuses the #64 NAMED build/cache, same ptr the union variant resolved to), mirroring the N_CAST/N_IDENT arms + cstage. Returns the body node unchanged (only e.type_ rides NAMED); struct-lit layout is unaffected -- cgstructlitfill is structlookup(name)-keyed, never reads NAMED.fields. The fix now hits all `T{}` stamps, kept byte-id by the #63/#65 structural-walker peels. 931_variant_typekey_run: table-driven, both stages, /tmp-isolated. Two rows widen an alias-FIRST variant from a call (no surface name): `(linerr|str)` str-via-call -> idx 1, `(ec|i32)` i32-via-call -> idx 1. Empirically discriminating: FAILS pre-flip (wwstage falls to the leading-shape variant, exit 10; cstage exit 0) and PASSES post-flip -- locking in the capability byte-id can't reach (the corpus has no name-key/type-key-disagreeing co-variant, which is why name-keying survived). make test 134/134 (byte-id 990-997 green; 995 self-rebuild green).
This commit is contained in:
@@ -667,7 +667,28 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
emitline("\tJNE\t");
|
||||
emitline(okl);
|
||||
emitline("\n");
|
||||
let nidx: i32 = flatvariantidx(c, c.fnret, "nomem");
|
||||
// #66 Phase-N step 3: nomem propagation has no
|
||||
// pattern node, so it can't ride the typeeq
|
||||
// flatvariantidx path. cstage passes the ty_nomem
|
||||
// singleton to cg_tag_for_variant; the wwstage cgen
|
||||
// holds no tinfo singleton, so find the nomem
|
||||
// variant by its NAMED name over tinfo.params.
|
||||
let nidx: i32 = -1;
|
||||
let nti: *tinfo = nil;
|
||||
if (c.fnret != nil) { nti = c.fnret.type_: *tinfo; };
|
||||
for (nti != nil && nti.kind == tykind.TY_NAMED) { nti = nti.under; };
|
||||
if (nti != nil) { if (nti.kind == tykind.TY_TAGGED) {
|
||||
let np: *tparam = nti.params;
|
||||
let nidx2: i32 = 0;
|
||||
for (np != nil) {
|
||||
let nvt: *tinfo = np.type_;
|
||||
if (nvt != nil) {
|
||||
if (variantnamematch(nvt.name, "nomem")) { nidx = nidx2; break; };
|
||||
};
|
||||
np = np.tnext;
|
||||
nidx2 += 1;
|
||||
};
|
||||
}; };
|
||||
if (nidx < 0) { nidx = 1; };
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(nidx: i64);
|
||||
|
||||
Reference in New Issue
Block a user