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

@@ -0,0 +1,12 @@
// crossmod — sibling module whose probe() takes a param named like the
// module `shadowmod` that paramshadowmod (NOT crossmod) imports. The
// shadow rule is filtered by the BINDING's own module (src_imports
// cur_mod filter): crossmod carries no `import shadowmod`, so this param
// must NOT trip even though a sibling module in the same bundle imports
// that leaf. Legit-form survivor of the abolished self-import tolerance.
package crossmod;
export fn probe(shadowmod: str) i32 = {
return shadowmod.len;
};

View File

@@ -0,0 +1,17 @@
// pos_crossmod — cur_mod-filtering positive. Replaces the abolished
// pos_selfimp (self-import is hard-rejected post-#16). This module
// (paramshadowmod) imports `shadowmod`, and the bundle also pulls module
// `crossmod`, whose probe() has a param named `shadowmod`. crossmod does
// NOT import shadowmod, so the shadow rule — filtered by the binding's
// own module — must NOT trip crossmod's param, even though a sibling
// module in the same bundle imports that leaf. Build + run; exit = 2.
package paramshadowmod;
import shadowmod;
import crossmod;
export fn main() i32 = {
let _ = shadowmod.say();
return crossmod.probe("hi");
};

View File

@@ -0,0 +1,3 @@
package foo;
import foo;
export fn main() int = { return 0; };