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:
7
Makefile
7
Makefile
@@ -581,10 +581,9 @@ DATABYTEID_EXPECTED_MIN = 911
|
|||||||
# Known cs!=ww divergences (loud over blind, the 989_lib_byteid DIVERGE
|
# Known cs!=ww divergences (loud over blind, the 989_lib_byteid DIVERGE
|
||||||
# discipline): each entry must still build on both stages AND still differ.
|
# discipline): each entry must still build on both stages AND still differ.
|
||||||
# When a compiler fix lands the entry fails demanding graduation out of
|
# When a compiler fix lands the entry fails demanding graduation out of
|
||||||
# this list rather than silently widening coverage. Tracked with the #59
|
# this list rather than silently widening coverage. Currently empty: the
|
||||||
# divergence family.
|
# 2026-08 drain closed all eight original entries.
|
||||||
DATABYTEID_DIVERGED = r76_typeeq_fn_diff_arity r76_typeeq_fn_diff_param_type \
|
DATABYTEID_DIVERGED =
|
||||||
r76_typeeq_fn_io_vtable_shape r76_typeeq_fn_variadic_vs_fixed
|
|
||||||
$(if $(DATABYTEID_FILES),,$(error test-byteid: empty data corpus))
|
$(if $(DATABYTEID_FILES),,$(error test-byteid: empty data corpus))
|
||||||
test-data-byteid: $(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww
|
test-data-byteid: $(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww
|
||||||
@work=$$(mktemp -d "$(CURDIR)/$(DATABYTEID_DIR).XXXXXX") || exit 1; \
|
@work=$$(mktemp -d "$(CURDIR)/$(DATABYTEID_DIR).XXXXXX") || exit 1; \
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ export type tparam = struct {
|
|||||||
// struct instead, matching cstage Type.iserror semantics.
|
// struct instead, matching cstage Type.iserror semantics.
|
||||||
// Faithful STORAGE_ERROR-node port filed as #62.
|
// Faithful STORAGE_ERROR-node port filed as #62.
|
||||||
iserror: bool,
|
iserror: bool,
|
||||||
|
// Hare-style `T...` — type_ is []T when set. Mirrors cstage
|
||||||
|
// Tparam.variadic (cmd/wcc/ww.h); distinct from tinfo.variadic,
|
||||||
|
// the C-style FFI `...` marker.
|
||||||
|
variadic: bool,
|
||||||
tnext: *tparam,
|
tnext: *tparam,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -547,6 +551,7 @@ export fn typeeq(a: *tinfo, b: *tinfo) bool = {
|
|||||||
for (true) {
|
for (true) {
|
||||||
if (pa == nil) { if (pb == nil) { return true; }; return false; };
|
if (pa == nil) { if (pb == nil) { return true; }; return false; };
|
||||||
if (pb == nil) { return false; };
|
if (pb == nil) { return false; };
|
||||||
|
if (pa.variadic != pb.variadic) { return false; };
|
||||||
if (!typeeq(pa.type_, pb.type_)) { return false; };
|
if (!typeeq(pa.type_, pb.type_)) { return false; };
|
||||||
pa = pa.tnext;
|
pa = pa.tnext;
|
||||||
pb = pb.tnext;
|
pb = pb.tnext;
|
||||||
|
|||||||
@@ -2311,6 +2311,32 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
|
|||||||
r.slotsize = 8u64;
|
r.slotsize = 8u64;
|
||||||
syntax.tinfocachebind(c.tc, n, r);
|
syntax.tinfocachebind(c.tc, n, r);
|
||||||
r.ret = tinfofornode(c, n.lhs);
|
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:
|
case syntax.nkind.N_TENUM:
|
||||||
// Cstage cmd/wcc/check.c:529-542: storage type's size/align
|
// Cstage cmd/wcc/check.c:529-542: storage type's size/align
|
||||||
// (default i32 = 4B/4B). Cgen's slotsize-TENUM fallback pads
|
// (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.size > maxsz) { maxsz = st.size; };
|
||||||
if (st.align > al) { al = st.align; };
|
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; };
|
if (head == nil) { head = tp; } else { tail.tnext = tp; };
|
||||||
tail = tp;
|
tail = tp;
|
||||||
nv += 1;
|
nv += 1;
|
||||||
@@ -2564,7 +2590,7 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
|
|||||||
if (vt.align > al) { al = vt.align; };
|
if (vt.align > al) { al = vt.align; };
|
||||||
};
|
};
|
||||||
let ve: bool = varianterr(c, v);
|
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; };
|
if (head == nil) { head = tp; } else { tail.tnext = tp; };
|
||||||
tail = tp;
|
tail = tp;
|
||||||
nv += 1;
|
nv += 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user