diff --git a/Makefile b/Makefile index d2c29ab4..2e672ba5 100644 --- a/Makefile +++ b/Makefile @@ -581,10 +581,9 @@ DATABYTEID_EXPECTED_MIN = 911 # Known cs!=ww divergences (loud over blind, the 989_lib_byteid DIVERGE # discipline): each entry must still build on both stages AND still differ. # When a compiler fix lands the entry fails demanding graduation out of -# this list rather than silently widening coverage. Tracked with the #59 -# divergence family. -DATABYTEID_DIVERGED = r76_typeeq_fn_diff_arity r76_typeeq_fn_diff_param_type \ - r76_typeeq_fn_io_vtable_shape r76_typeeq_fn_variadic_vs_fixed +# this list rather than silently widening coverage. Currently empty: the +# 2026-08 drain closed all eight original entries. +DATABYTEID_DIVERGED = $(if $(DATABYTEID_FILES),,$(error test-byteid: empty data corpus)) test-data-byteid: $(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww @work=$$(mktemp -d "$(CURDIR)/$(DATABYTEID_DIR).XXXXXX") || exit 1; \ diff --git a/lib/ww/syntax/typ.ww b/lib/ww/syntax/typ.ww index 785d2432..a18e33e6 100644 --- a/lib/ww/syntax/typ.ww +++ b/lib/ww/syntax/typ.ww @@ -88,6 +88,10 @@ export type tparam = struct { // struct instead, matching cstage Type.iserror semantics. // Faithful STORAGE_ERROR-node port filed as #62. 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, }; @@ -547,6 +551,7 @@ export fn typeeq(a: *tinfo, b: *tinfo) bool = { for (true) { if (pa == nil) { if (pb == nil) { return true; }; return false; }; if (pb == nil) { return false; }; + if (pa.variadic != pb.variadic) { return false; }; if (!typeeq(pa.type_, pb.type_)) { return false; }; pa = pa.tnext; pb = pb.tnext; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 776f639a..8cb6957f 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -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;