From f0029227b582fdecf3df3c6c2e7212387e185003 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sun, 9 Aug 2026 00:15:10 +0900 Subject: [PATCH] wcc: cgdot/cgident dead-end paths are loud (rule 7) cgdot's local-ident arm silently emitted nothing for a receiver whose local record carries no type node (inference miss upstream), leaving the consumer reading stale AX. cgident's tail silently emitted nothing for any ident that resolved to no local/fn/def/let; that silence is load-bearing ONLY for the #140 !void error-singleton value (tag-only, the widen arm stamps the tag) -- keep exactly that case, mirroring the cstage #140 guard, and hard-stop the rest. --- selfhost/cmd/wcc/cgenexpr.ww | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/selfhost/cmd/wcc/cgenexpr.ww b/selfhost/cmd/wcc/cgenexpr.ww index 8e7c8d79..119b734f 100644 --- a/selfhost/cmd/wcc/cgenexpr.ww +++ b/selfhost/cmd/wcc/cgenexpr.ww @@ -1388,7 +1388,19 @@ fn cgident(c: *cgen, n: *syntax.node) void = { }; return; }; - return; + // #140: a `!void` error-singleton spelled as a VALUE (`return + // toolong;`) is tag-only — the void payload has size 0 and no + // storage, so it is neither a local, def, nor let. Emit NOTHING; + // the enclosing widen arm stamps the variant tag. Mirrors cstage + // cgen.c N_IDENT #140 guard. Every other unresolvable ident is + // checker-rejected upstream — loud, never the old silent return. + { + let vu: *syntax.tinfo = tichase(n.type_: *syntax.tinfo); + if (vu != nil && vu.kind == syntax.tykind.TY_VOID) { return; }; + }; + let mur: str = "cgident: unresolvable identifier (rule 7)\n"; + os.write(2, mur.ptr, mur.len: u64); + os.exit(1); }; // cgslicehdr — load the 24B slice/str header at base+0 into the @@ -3707,7 +3719,16 @@ fn cgdot(c: *cgen, n: *syntax.node) void = { }; tn = nx; }; - if (tn == nil) { return; }; + // A registered local with NO type node means + // inference missed upstream — emitting nothing + // leaves the consumer reading stale AX, and + // falling through would emit a bogus + // `MOVQ (SB)` (the #191 hazard). Loud. + if (tn == nil) { + let mdt: str = "cgdot: local receiver has no type node (rule 7)\n"; + os.write(2, mdt.ptr, mdt.len: u64); + os.exit(1); + }; let lkind: syntax.nkind = tn.kind; // Pointer-to-struct: deref then field load. if (lkind == syntax.nkind.N_TPTR) {