ww imports: reject init bindings before recovery
This commit is contained in:
@@ -175,6 +175,11 @@ fn declmod(file: *syntax.node, d: *syntax.node) str = {
|
||||
return empty;
|
||||
};
|
||||
|
||||
fn invalidinitimport(u: *syntax.node) bool = {
|
||||
return u != nil && u.kind == syntax.nkind.N_USE && u.useblank == 0
|
||||
&& syntax.streq(u.str, "init");
|
||||
};
|
||||
|
||||
// Map a source-file qualifier to canonical identity. Looking up the marker for
|
||||
// a possible DOT must not itself count as usage; only qualified resolution
|
||||
// marks the owning occurrence.
|
||||
@@ -192,6 +197,7 @@ fn findusepath(file: *syntax.node, modtag: str, source: i32, alias: str,
|
||||
let u: *syntax.node = file.list;
|
||||
for (u != nil) {
|
||||
if (u.kind == syntax.nkind.N_USE && u.useblank == 0
|
||||
&& !invalidinitimport(u)
|
||||
&& u.sourceid == source) {
|
||||
if (syntax.streq(u.str, alias)) {
|
||||
let um: str = declmod(file, u);
|
||||
@@ -425,12 +431,7 @@ fn installdecl(c: *checker, file: *syntax.node, d: *syntax.node) void = {
|
||||
cerr("' cannot import itself\n"); c.errs += 1i32;
|
||||
};
|
||||
if (d.useblank != 0) { return; };
|
||||
if (syntax.streq(nm, "init")) {
|
||||
importdiagprefix(d);
|
||||
cerr("cannot import package as init - init must be a func\n");
|
||||
c.errs += 1;
|
||||
return;
|
||||
};
|
||||
if (invalidinitimport(d)) { return; };
|
||||
// #30 value-before-use: a same-leaf VALUE/type decl is already
|
||||
// installed (source order placed `fn aa` before `import aa`).
|
||||
// Promote it in place with use_alias instead of installing a
|
||||
@@ -7527,6 +7528,20 @@ fn importdiagprefix(n: *syntax.node) void = {
|
||||
cerr(strconv.i32tos(n.col, strconv.base.DEC)); cerr(": error: ");
|
||||
};
|
||||
|
||||
fn importbindingdiagprefix(n: *syntax.node) void = {
|
||||
let file: str = n.usefile;
|
||||
let line: i32 = n.useline;
|
||||
let col: i32 = n.usecol;
|
||||
if (file.len == 0) {
|
||||
file = n.file;
|
||||
line = n.line;
|
||||
col = n.col;
|
||||
};
|
||||
cerr(file); cerr(":");
|
||||
cerr(strconv.i32tos(line, strconv.base.DEC)); cerr(":");
|
||||
cerr(strconv.i32tos(col, strconv.base.DEC)); cerr(": error: ");
|
||||
};
|
||||
|
||||
fn importdiagalt(n: *syntax.node, name: str) void = {
|
||||
cerr("\t"); cerr(n.file); cerr(":");
|
||||
cerr(strconv.i32tos(n.line, strconv.base.DEC)); cerr(":");
|
||||
@@ -7534,6 +7549,22 @@ fn importdiagalt(n: *syntax.node, name: str) void = {
|
||||
cerr(": other declaration of "); cerr(name); cerr("\n");
|
||||
};
|
||||
|
||||
// Pinned Go 1.26.5 types2 rejects an effective import binding named init and
|
||||
// immediately continues before creating its PkgName. Diagnose every resolved
|
||||
// occurrence at the first import-spec token, while retaining its loader-owned
|
||||
// dependency edge and excluding it from binding recovery below.
|
||||
fn rejectinitimports(c: *checker, file: *syntax.node) void = {
|
||||
let u: *syntax.node = file.list;
|
||||
for (u != nil) {
|
||||
if (invalidinitimport(u)) {
|
||||
importbindingdiagprefix(u);
|
||||
cerr("cannot import package as init - init must be a func\n");
|
||||
c.errs += 1;
|
||||
};
|
||||
u = u.next;
|
||||
};
|
||||
};
|
||||
|
||||
fn topdeclkind(d: *syntax.node) bool = {
|
||||
return d != nil && (d.kind == syntax.nkind.N_TYPEDECL
|
||||
|| d.kind == syntax.nkind.N_DEF || d.kind == syntax.nkind.N_FNDECL
|
||||
@@ -7581,10 +7612,12 @@ fn checkimportredeclarations(c: *checker, file: *syntax.node) void = {
|
||||
let u: *syntax.node = file.list;
|
||||
for (u != nil) {
|
||||
if (u.kind == syntax.nkind.N_USE && u.useblank == 0
|
||||
&& !invalidinitimport(u)
|
||||
&& u.imported == 0) {
|
||||
let v: *syntax.node = file.list;
|
||||
for (v != u) {
|
||||
if (v.kind == syntax.nkind.N_USE && v.useblank == 0
|
||||
&& !invalidinitimport(v)
|
||||
&& v.imported == 0
|
||||
&& v.sourceid == u.sourceid && syntax.streq(v.str, u.str)) {
|
||||
importdiagprefix(u); cerr(u.str);
|
||||
@@ -7605,6 +7638,7 @@ fn checkimportusageandcollisions(c: *checker, file: *syntax.node) void = {
|
||||
let u: *syntax.node = file.list;
|
||||
for (u != nil) {
|
||||
if (u.kind == syntax.nkind.N_USE && u.useblank == 0
|
||||
&& !invalidinitimport(u)
|
||||
&& u.imported == 0 && u.used == 0) {
|
||||
let path: str = u.usesource;
|
||||
if (path.len == 0) { path = u.usepath; };
|
||||
@@ -7629,6 +7663,7 @@ fn checkimportusageandcollisions(c: *checker, file: *syntax.node) void = {
|
||||
u = file.list;
|
||||
for (u != nil) {
|
||||
if (u.kind == syntax.nkind.N_USE && u.useblank == 0
|
||||
&& !invalidinitimport(u)
|
||||
&& u.imported == 0
|
||||
&& syntax.streq(d.str, u.str)) {
|
||||
let path: str = u.usesource;
|
||||
@@ -8608,6 +8643,7 @@ fn checkfile(c: *checker, file: *syntax.node) void = {
|
||||
file.list = usenode;
|
||||
};
|
||||
};
|
||||
rejectinitimports(c, file);
|
||||
rejectnonfunctionmaindecls(c, file);
|
||||
markimportuses(c, file);
|
||||
checkimportredeclarations(c, file);
|
||||
|
||||
Reference in New Issue
Block a user