check: populate fn-type params in the wwstage tinfo layer

The N_TFN arm stamped only size and return, so every fn tinfo carried
a nil param chain and typeeq judged any two same-return fn types
equal: tagged-union dedup collapsed (*fn(A) T | *fn(B) T) to a bare
8-byte pointer and match read the pointer word as a tag, falling
through every arm for a real second-variant value. Build the tparam
chain like cstage's N_TFN resolve (bare ... sets the FFI variadic
flag; a Hare T... param wraps to []T with a per-param variadic bit
that typeeq now compares, mirroring cstage type_eq). Graduates the
four r76_typeeq_fn pins; the DATABYTEID_DIVERGED ledger is empty.
This commit is contained in:
2026-08-07 23:54:10 +09:00
parent 06c20dbec4
commit 0b1cc5ef7c
3 changed files with 36 additions and 6 deletions

View File

@@ -2311,6 +2311,32 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
r.slotsize = 8u64;
syntax.tinfocachebind(c.tc, n, r);
r.ret = tinfofornode(c, n.lhs);
// Params must be populated (cstage check.c N_TFN builds the
// Tparam chain): with params nil on every fn tinfo, typeeq saw
// any two same-return fn types equal, so tagged-union dedup
// collapsed `(*fn(A) T | *fn(B) T)` to a bare 8B pointer and
// match read the pointer word as a tag.
{
let fphead: *syntax.tparam = nil;
let fptail: *syntax.tparam = nil;
let fpn: *syntax.node = n.list;
for (fpn != nil) {
if (syntax.streq(fpn.str, "...")) {
r.variadic = 1;
fpn = fpn.next;
continue;
};
let fpt: *syntax.tinfo = tinfofornode(c, fpn.lhs);
let fpv: bool = fpn.op == syntax.tkind.TK_ELLIPSIS;
if (fpv) { fpt = syntax.typeslice(fpt); };
let ftp: *syntax.tparam = alloc(syntax.tparam{name=fpn.str, type_=fpt, iserror=false, variadic=fpv, tnext=nil})!;
if (fphead == nil) { fphead = ftp; }
else { fptail.tnext = ftp; };
fptail = ftp;
fpn = fpn.next;
};
r.params = fphead;
};
case syntax.nkind.N_TENUM:
// Cstage cmd/wcc/check.c:529-542: storage type's size/align
// (default i32 = 4B/4B). Cgen's slotsize-TENUM fallback pads
@@ -2546,7 +2572,7 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
if (st.size > maxsz) { maxsz = st.size; };
if (st.align > al) { al = st.align; };
};
let tp: *syntax.tparam = alloc(syntax.tparam{name="", type_=src.type_, iserror=src.iserror, tnext=nil})!;
let tp: *syntax.tparam = alloc(syntax.tparam{name="", type_=src.type_, iserror=src.iserror, variadic=false, tnext=nil})!;
if (head == nil) { head = tp; } else { tail.tnext = tp; };
tail = tp;
nv += 1;
@@ -2564,7 +2590,7 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
if (vt.align > al) { al = vt.align; };
};
let ve: bool = varianterr(c, v);
let tp: *syntax.tparam = alloc(syntax.tparam{name="", type_=vt, iserror=ve, tnext=nil})!;
let tp: *syntax.tparam = alloc(syntax.tparam{name="", type_=vt, iserror=ve, variadic=false, tnext=nil})!;
if (head == nil) { head = tp; } else { tail.tnext = tp; };
tail = tp;
nv += 1;