wcc: kind-agnostic typeeq dispatch in cgmatch non-nullable arm (#179)
cgmatch's non-nullable variant-tag synthesis gated flatvariantidx on pat.kind == N_TNAME (with N_TSLICE else-branch for #19's untyped-elem fallback). N_TPTR / N_TFN / N_TPTR(N_TFN) case-patterns fell through both, leaving r=-1 → want=0 so every variant past 0 silently collapsed to tag 0 — runtime-passes only when the value happens to sit on variant 0 (zero-coincidence miscompile). Cstage cg_tag_for_variant works on resolved Type and is kind- agnostic; harec stores `_case->type = ctype` (ref/harec check.c:2527). #66 Phase-N already flipped match dispatch to typeeq; #179 is the last site still keyed on AST kind. Memory: project_tinfo_lossy_nominal + feedback "Hare = resolved-type-only match dispatch". Route through flatvariantidxt(scrutt.type_, pat.type_) directly, guarded by istaggedtype + typeisslice(pattype) for the slice axis. No new helper — existing flatvariantidxt / flatslicevariantidx wire up unchanged. 767 probe locks the fix across 5 rows: (1) nullable *fn branched store (ken's verify gate — proves the nullable arm at line 1484 isn't perturbed); (2) *i32|*i64 storing &i64 — pre-fix wwstage emitted CMPQ $0 for *i64 arm, post-fix CMPQ $1; (3) *fn(i32)|*fn(i64) via intermediate local; (4) branched runtime variant choice defeats const-fold; (5) aliased ptr variants (typeeq through TY_NAMED). Per row: cs runtime, ww runtime, cs.s == ww.s byte-id. Sibling filed inline: widening `&fn` INLINE into a fn-ptr-only tagged union picks tag 0 in wwstage's cgwidentaggedstorebp (out-of-scope; row 3 dodges via intermediate ident store).
This commit is contained in:
@@ -19069,16 +19069,22 @@ fn cgmatch(c: *cgen, n: *node) void = {
|
||||
// rather than the resolved N_TTAGGED node.
|
||||
if (istaggedtype(c, scrutt)) {
|
||||
let r: i32 = -1;
|
||||
if (pat.kind == nkind.N_TNAME) {
|
||||
r = flatvariantidx(c, scrutt, pat);
|
||||
} else { if (pat.kind == nkind.N_TSLICE) {
|
||||
// `case let s: []T =>` — pat.str is empty
|
||||
// because the variant is a composite, so
|
||||
// route through the slice-shape helper.
|
||||
// Without this every (scalar | []T) match
|
||||
// arm collapses to tag 0 (task #19).
|
||||
r = flatslicevariantidx(c, scrutt, pat.lhs);
|
||||
}; };
|
||||
let pattype: *tinfo = pat.type_: *tinfo;
|
||||
if (pattype != nil) {
|
||||
// #179: kind-agnostic dispatch on the resolved
|
||||
// tinfo. Cstage cg_tag_for_variant works on
|
||||
// Type, so N_TPTR / N_TFN / N_TPTR(N_TFN) case-
|
||||
// patterns all reach typeeq; the prior pat.kind
|
||||
// gate dropped them to r=-1 → tag 0 collapse.
|
||||
// Slice arm still goes through flatslicevariantidx
|
||||
// (task #19 untyped-elem fallback when typeeq
|
||||
// can't match a (scalar | []T) shape).
|
||||
if (typeisslice(pattype)) {
|
||||
r = flatslicevariantidx(c, scrutt, pat.lhs);
|
||||
} else {
|
||||
r = flatvariantidxt(scrutt.type_: *tinfo, pattype);
|
||||
};
|
||||
};
|
||||
if (r >= 0) { want = r; };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1509,16 +1509,22 @@ fn cgmatch(c: *cgen, n: *node) void = {
|
||||
// rather than the resolved N_TTAGGED node.
|
||||
if (istaggedtype(c, scrutt)) {
|
||||
let r: i32 = -1;
|
||||
if (pat.kind == nkind.N_TNAME) {
|
||||
r = flatvariantidx(c, scrutt, pat);
|
||||
} else { if (pat.kind == nkind.N_TSLICE) {
|
||||
// `case let s: []T =>` — pat.str is empty
|
||||
// because the variant is a composite, so
|
||||
// route through the slice-shape helper.
|
||||
// Without this every (scalar | []T) match
|
||||
// arm collapses to tag 0 (task #19).
|
||||
r = flatslicevariantidx(c, scrutt, pat.lhs);
|
||||
}; };
|
||||
let pattype: *tinfo = pat.type_: *tinfo;
|
||||
if (pattype != nil) {
|
||||
// #179: kind-agnostic dispatch on the resolved
|
||||
// tinfo. Cstage cg_tag_for_variant works on
|
||||
// Type, so N_TPTR / N_TFN / N_TPTR(N_TFN) case-
|
||||
// patterns all reach typeeq; the prior pat.kind
|
||||
// gate dropped them to r=-1 → tag 0 collapse.
|
||||
// Slice arm still goes through flatslicevariantidx
|
||||
// (task #19 untyped-elem fallback when typeeq
|
||||
// can't match a (scalar | []T) shape).
|
||||
if (typeisslice(pattype)) {
|
||||
r = flatslicevariantidx(c, scrutt, pat.lhs);
|
||||
} else {
|
||||
r = flatvariantidxt(scrutt.type_: *tinfo, pattype);
|
||||
};
|
||||
};
|
||||
if (r >= 0) { want = r; };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19069,16 +19069,22 @@ fn cgmatch(c: *cgen, n: *node) void = {
|
||||
// rather than the resolved N_TTAGGED node.
|
||||
if (istaggedtype(c, scrutt)) {
|
||||
let r: i32 = -1;
|
||||
if (pat.kind == nkind.N_TNAME) {
|
||||
r = flatvariantidx(c, scrutt, pat);
|
||||
} else { if (pat.kind == nkind.N_TSLICE) {
|
||||
// `case let s: []T =>` — pat.str is empty
|
||||
// because the variant is a composite, so
|
||||
// route through the slice-shape helper.
|
||||
// Without this every (scalar | []T) match
|
||||
// arm collapses to tag 0 (task #19).
|
||||
r = flatslicevariantidx(c, scrutt, pat.lhs);
|
||||
}; };
|
||||
let pattype: *tinfo = pat.type_: *tinfo;
|
||||
if (pattype != nil) {
|
||||
// #179: kind-agnostic dispatch on the resolved
|
||||
// tinfo. Cstage cg_tag_for_variant works on
|
||||
// Type, so N_TPTR / N_TFN / N_TPTR(N_TFN) case-
|
||||
// patterns all reach typeeq; the prior pat.kind
|
||||
// gate dropped them to r=-1 → tag 0 collapse.
|
||||
// Slice arm still goes through flatslicevariantidx
|
||||
// (task #19 untyped-elem fallback when typeeq
|
||||
// can't match a (scalar | []T) shape).
|
||||
if (typeisslice(pattype)) {
|
||||
r = flatslicevariantidx(c, scrutt, pat.lhs);
|
||||
} else {
|
||||
r = flatvariantidxt(scrutt.type_: *tinfo, pattype);
|
||||
};
|
||||
};
|
||||
if (r >= 0) { want = r; };
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user