diff --git a/internal/wwfixture/types.ww b/internal/wwfixture/types.ww index 08d4c239..f65056c3 100644 --- a/internal/wwfixture/types.ww +++ b/internal/wwfixture/types.ww @@ -1,13 +1,13 @@ package wwfixture; def protocolversion: i32 = 1; -def corpuscount: i32 = 1237; +def corpuscount: i32 = 1238; def errorcount: i32 = 314; def compilecount: i32 = 12; def runcount: i32 = 145; -def runexitcount: i32 = 766; -def nativecount: i32 = 2474; -def corpushash: str = "7763f2eb34524f67355114f5bdfbf3f64415152a8ec64060fe32a322bdbe1b24"; +def runexitcount: i32 = 767; +def nativecount: i32 = 2476; +def corpushash: str = "a78db801f50ad02de11fed981bd6d9c2d67509e69a69615744f1b2ad3ef4814d"; type directive = enum i32 { ERROR = 0, diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 3ebb6726..0d74a6bb 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -3310,6 +3310,26 @@ fn exprtype(c: *checker, e: *syntax.node, hint: *syntax.node) *syntax.node = { e.type_ = tinfofornode(c, ft): *void; return ft; }; + // #142: a TYPE name used as a VALUE (an error-singleton + // `return too_long;`) must stamp the per-decl NAMED, not the + // flattened body — three structurally identical !void + // singletons in one union are indistinguishable by body, so + // flatvariantidxt's NAMED pass either mis-tags or + // loud-rejects as ambiguous. Resolve through a synthesized + // TNAME to reuse tinfofornode's TY_NAMED build/cache (the + // SAME NAMED ptr the union variant resolved to) — the #66 + // N_STRUCTLIT precedent verbatim; cstage mirror + // cmd/wcc/check.c:1414 `n->type = s->type`. The BODY node + // still returns so AST-level assign/return checks keep + // their prior input. + if (s.skind == syntax.skind.SK_TYPE) { + let tnm: *syntax.node = mktname(c, e.str); + let nti: *syntax.tinfo = tinfofornode(c, tnm); + if (nti != nil) { + e.type_ = nti: *void; + return s.decl.lhs; + }; + }; let t: *syntax.node = s.decl.lhs; // Propagate the declared type's tinfo onto the use site so // downstream cgen walkers can read n.type_ off an ident. @@ -3878,6 +3898,19 @@ fn exprtype(c: *checker, e: *syntax.node, hint: *syntax.node) *syntax.node = { e.type_ = tinfofornode(c, ft): *void; return ft; }; + // #142 twin of the N_IDENT SK_TYPE arm: a + // module-qualified TYPE name used as a VALUE + // (`mod.too_long`) stamps the per-decl NAMED. + // The sym caches its NAMED (tinfofornode + // N_TNAME arm) once any type-position ref + // resolved; a nil cache falls through to the + // prior body stamp. + if (fs.skind == syntax.skind.SK_TYPE) { + if (fs.type_ != nil) { + e.type_ = fs.type_: *void; + return fs.decl.lhs; + }; + }; let tn: *syntax.node = fs.decl.lhs; if (tn != nil) { e.type_ = tinfofornode(c, tn): *void; diff --git a/test/wcc/989_lib_byteid.c b/test/wcc/989_lib_byteid.c index 642f16ef..5c6e02e3 100644 --- a/test/wcc/989_lib_byteid.c +++ b/test/wcc/989_lib_byteid.c @@ -117,14 +117,16 @@ static const struct ent ents[] = { /* fixtureless modules, import-probe shape */ { .probe = "package main;\nimport sort;\nfn main() i32 = { return 0; };\n", .mode = M_ID, .sentinel = "package sort;", .moddir = "lib/sort" }, - /* c2-stack path::buffer realignment: w6c compiles, w6c_ww rejects - * path's module-global slice consts (const dot/dotdot: []u8) = the - * #120/#29 acceptance divergence (module-level composite globals); - * + the #148 twin #151 (global []u8 by-value arg). Both → #125 - * batch. cstage runtime is covered by 989_path_run. M_WWREJECT - * self-graduates: flips RED to M_ID the day wwstage accepts this. */ + /* #142 graduated (the old #120/#29 global-slice-const blame was + * stale — that family drained earlier): path declares three + * structurally identical !void error singletons, and a VALUE use + * (`return too_long;`) stamped the flattened BODY type, so + * flatvariantidxt loud-rejected the ambiguity. The SK_TYPE value + * arms now stamp the per-decl NAMED (the #66 N_STRUCTLIT + * precedent). Runtime pin: r142_singleton_value_named. */ { .probe = "package main;\nimport path;\nfn main() i32 = { return 0; };\n", - .mode = M_WWREJECT, .cite = "#120/#29", .sentinel = "package path;", .moddir = "lib/path" }, + .mode = M_ID, .cite = "#142 graduated by the SK_TYPE NAMED value stamp", + .sentinel = "package path;", .moddir = "lib/path" }, { .probe = "package main;\nimport endian;\nfn main() i32 = { return 0; };\n", .mode = M_ID, .sentinel = "package endian;", .moddir = "lib/endian" }, { .probe = "package main;\nimport net;\nfn main() i32 = { return 0; };\n", diff --git a/test/wcc/data/r142_singleton_value_named/case.ww b/test/wcc/data/r142_singleton_value_named/case.ww new file mode 100644 index 00000000..fd5a7242 --- /dev/null +++ b/test/wcc/data/r142_singleton_value_named/case.ww @@ -0,0 +1,23 @@ +//ww:run-exit 42 +// #142: a VALUE use of an error-singleton type name whose union has +// structurally identical siblings. The pre-fix wwstage stamped the +// flattened BODY type (!void), so flatvariantidxt could not pick a +// variant and loud-rejected; the per-decl NAMED stamp discriminates. +// Exit 42 proves the SECOND variant is selected, not the first. +package main; + +type a = !void; +type b = !void; +type err = !(a | b); + +fn f() err = { + return b; +}; + +fn main() i32 = { + match (f()) { + case a => { return 41; }; + case b => { return 42; }; + }; + return 9; +};