wcc/check: reject self-import, both stages (#16 ENFORCE-checker)

check-(c): a package importing itself (any spelling) is a hard error,
mirroring Go. Predicate is leaf==owner at the N_USE/installdecl seam —
sound only after the PREP commits (dotted-test renames, package-less
boundary directive). Identical wording both stages; diagnostics-only,
byte-id-neutral. 948 pins the reject in both compilers; 708's
pos_selfimp (which pinned the abolished self-import skip) converts to
neg_selfimp + new pos_crossmod preserving the param-shadow tolerance
the case existed for. Checks (a) unused and (b)/(d) name-membership
stay deferred to the multi-package arc: imports are filename-keyed
pulls, so those need import->file provenance this compiler lacks.
This commit is contained in:
2026-06-10 15:18:58 +09:00
parent 49a5173f3f
commit 9f8df525c2
10 changed files with 266 additions and 35 deletions

View File

@@ -10607,7 +10607,18 @@ fn installdecl(c: *checker, file: *node, d: *node) void = {
let k: nkind = d.kind;
let nm: str = d.str;
let mod: str = declmod(file, d);
if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; };
// check-(c) self-import: a package may not import itself. Pure
// owner==leaf string compare, package-model-independent. check-(a)
// unused + (b)/(d) membership DEFERRED to task #8 (filename-keyed
// pulls lack import->file->symbol provenance). Message byte-identical
// to cstage check.c.
if (k == nkind.N_USE) {
if (mod.len != 0 && streq(nm, mod)) {
cerr("self-import: package '"); cerr(mod);
cerr("' cannot import itself\n"); c.errs += 1i32;
};
scopedefine(c.top, nm, skind.SK_USE, nil, d); return;
};
if (k == nkind.N_DEF) { scopedefineinmodule(c.top, nm, mod, skind.SK_DEF, nil, d); return; };
if (k == nkind.N_TYPEDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_TYPE, nil, d); return; };
if (k == nkind.N_FNDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_FN, nil, d); return; };

View File

@@ -275,7 +275,18 @@ fn installdecl(c: *checker, file: *node, d: *node) void = {
let k: nkind = d.kind;
let nm: str = d.str;
let mod: str = declmod(file, d);
if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; };
// check-(c) self-import: a package may not import itself. Pure
// owner==leaf string compare, package-model-independent. check-(a)
// unused + (b)/(d) membership DEFERRED to task #8 (filename-keyed
// pulls lack import->file->symbol provenance). Message byte-identical
// to cstage check.c.
if (k == nkind.N_USE) {
if (mod.len != 0 && streq(nm, mod)) {
cerr("self-import: package '"); cerr(mod);
cerr("' cannot import itself\n"); c.errs += 1i32;
};
scopedefine(c.top, nm, skind.SK_USE, nil, d); return;
};
if (k == nkind.N_DEF) { scopedefineinmodule(c.top, nm, mod, skind.SK_DEF, nil, d); return; };
if (k == nkind.N_TYPEDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_TYPE, nil, d); return; };
if (k == nkind.N_FNDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_FN, nil, d); return; };

View File

@@ -10607,7 +10607,18 @@ fn installdecl(c: *checker, file: *node, d: *node) void = {
let k: nkind = d.kind;
let nm: str = d.str;
let mod: str = declmod(file, d);
if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; };
// check-(c) self-import: a package may not import itself. Pure
// owner==leaf string compare, package-model-independent. check-(a)
// unused + (b)/(d) membership DEFERRED to task #8 (filename-keyed
// pulls lack import->file->symbol provenance). Message byte-identical
// to cstage check.c.
if (k == nkind.N_USE) {
if (mod.len != 0 && streq(nm, mod)) {
cerr("self-import: package '"); cerr(mod);
cerr("' cannot import itself\n"); c.errs += 1i32;
};
scopedefine(c.top, nm, skind.SK_USE, nil, d); return;
};
if (k == nkind.N_DEF) { scopedefineinmodule(c.top, nm, mod, skind.SK_DEF, nil, d); return; };
if (k == nkind.N_TYPEDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_TYPE, nil, d); return; };
if (k == nkind.N_FNDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_FN, nil, d); return; };