wcc: reject module-scope alloc/call let initializers at check time

A module-scope let whose rhs runs code (alloc, call — peeled through
cast/?/! wrappers) emitted no DATAW slot: emit_lets' fold-fail
silently skipped the definition and every reference died at LINK
time with 'undefined reference', the one unacceptable failure mode
(rule 7). Hare's model rejects at check time (ref/harec/src/
check.c:4360 'Unable to evaluate initializer at compile time') and
routes runtime init through @init, which ww does not have — so both
frontends now reject at the declaration with identical wording.

alias_infptr_global flips compile->error as the alloc pin (its
letvartnode N_TPTR-over-N_TSTRUCT coverage lives on in the local
alias_infptr_{nest,slicecap} siblings); callinit_global_reject pins
the call shape. Corpus pin 1741/345/21/209/1166/3482.
This commit is contained in:
2026-08-08 19:15:10 +09:00
parent 84206ff4ed
commit b52f30a894
5 changed files with 65 additions and 9 deletions

View File

@@ -343,7 +343,32 @@ fn installdecl(c: *checker, file: *syntax.node, d: *syntax.node) void = {
if (k == syntax.nkind.N_DEF) { installtop(c, d, nm, mod, syntax.skind.SK_DEF, "def"); return; };
if (k == syntax.nkind.N_TYPEDECL) { installtop(c, d, nm, mod, syntax.skind.SK_TYPE, "type"); return; };
if (k == syntax.nkind.N_FNDECL) { installtop(c, d, nm, mod, syntax.skind.SK_FN, "fn"); return; };
if (k == syntax.nkind.N_LET) { installtop(c, d, nm, mod, syntax.skind.SK_VAR, "let"); return; };
if (k == syntax.nkind.N_LET) {
// A module-scope initializer must be link-time data: an
// alloc/call rhs runs code, emitletdataw's fold-fail
// skipped the DATAW slot silently, and every reference
// died at LINK time ("undefined reference") — reject at
// the declaration instead (rule 7). Hare rejects at check
// time too (ref/harec/src/check.c:4360); ww has no @init
// path. Mirrors cstage check_file N_LET.
let rr: *syntax.node = d.rhs;
for (rr != nil) {
if (rr.kind == syntax.nkind.N_CAST) { rr = rr.lhs; continue; };
if (rr.kind == syntax.nkind.N_TRYPROP) { rr = rr.lhs; continue; };
if (rr.kind == syntax.nkind.N_TRYUNW) { rr = rr.lhs; continue; };
break;
};
if (rr != nil) {
if (rr.kind == syntax.nkind.N_ALLOC || rr.kind == syntax.nkind.N_CALL) {
cerr(d.file); cerr(": error: module-scope let ");
cerr(nm);
cerr(": runtime initializer unsupported (alloc/call; rule 7)\n");
c.errs += 1;
};
};
installtop(c, d, nm, mod, syntax.skind.SK_VAR, "let");
return;
};
};
// installtop — install a top-level decl name into c.top, rejecting a