mirror of
https://github.com/golang/go
synced 2024-11-21 22:44:40 -07:00
gc: add -p flag to catch import cycles earlier
The linker would catch them if gc succeeded, but too often the cycle manifests as making the current package and the imported copy of itself appear as different packages, which result in type signature mismatches that confuse users. As a crutch, add the -p flag to say 'if you see an import of this package, give up early'. Results in messages like (during gotest in sort): export_test.go:7: import "sort" while compiling that package (import cycle) export_test.go:7: import "container/heap": package depends on "sort" (import cycle) Fixes #2042. R=ken CC=bradfitz, dsymonds, golang-dev https://golang.org/cl/4972057
This commit is contained in:
parent
ef01ebf403
commit
1e480cd1ad
@ -83,10 +83,10 @@ $(TARGDIR)/$(TARG).a: _obj/$(TARG).a
|
|||||||
cp _obj/$(TARG).a "$@"
|
cp _obj/$(TARG).a "$@"
|
||||||
|
|
||||||
_go_.$O: $(GOFILES) $(PREREQ)
|
_go_.$O: $(GOFILES) $(PREREQ)
|
||||||
$(GC) $(GCIMPORTS) -o $@ $(GOFILES)
|
$(GC) $(GCIMPORTS) -p $(TARG) -o $@ $(GOFILES)
|
||||||
|
|
||||||
_gotest_.$O: $(GOFILES) $(GOTESTFILES) $(PREREQ)
|
_gotest_.$O: $(GOFILES) $(GOTESTFILES) $(PREREQ)
|
||||||
$(GC) $(GCIMPORTS) -o $@ $(GOFILES) $(GOTESTFILES)
|
$(GC) $(GCIMPORTS) -p $(TARG) -o $@ $(GOFILES) $(GOTESTFILES)
|
||||||
|
|
||||||
_obj/$(TARG).a: _go_.$O $(OFILES)
|
_obj/$(TARG).a: _go_.$O $(OFILES)
|
||||||
@mkdir -p _obj/$(dir)
|
@mkdir -p _obj/$(dir)
|
||||||
|
@ -35,6 +35,9 @@ Flags:
|
|||||||
output file, default file.6 for 6g, etc.
|
output file, default file.6 for 6g, etc.
|
||||||
-e
|
-e
|
||||||
normally the compiler quits after 10 errors; -e prints all errors
|
normally the compiler quits after 10 errors; -e prints all errors
|
||||||
|
-p path
|
||||||
|
assume that path is the eventual import path for this code,
|
||||||
|
and diagnose any attempt to import a package that depends on it.
|
||||||
-L
|
-L
|
||||||
show entire file path when printing line numbers in errors
|
show entire file path when printing line numbers in errors
|
||||||
-I dir1 -I dir2
|
-I dir1 -I dir2
|
||||||
|
@ -773,6 +773,7 @@ EXTERN Pkg* phash[128];
|
|||||||
EXTERN int tptr; // either TPTR32 or TPTR64
|
EXTERN int tptr; // either TPTR32 or TPTR64
|
||||||
extern char* runtimeimport;
|
extern char* runtimeimport;
|
||||||
extern char* unsafeimport;
|
extern char* unsafeimport;
|
||||||
|
EXTERN char* myimportpath;
|
||||||
EXTERN Idir* idirs;
|
EXTERN Idir* idirs;
|
||||||
|
|
||||||
EXTERN Type* types[NTYPE];
|
EXTERN Type* types[NTYPE];
|
||||||
|
@ -243,11 +243,11 @@ import_package:
|
|||||||
importpkg->name = $2->name;
|
importpkg->name = $2->name;
|
||||||
pkglookup($2->name, nil)->npkg++;
|
pkglookup($2->name, nil)->npkg++;
|
||||||
} else if(strcmp(importpkg->name, $2->name) != 0)
|
} else if(strcmp(importpkg->name, $2->name) != 0)
|
||||||
yyerror("conflicting names %s and %s for package %Z", importpkg->name, $2->name, importpkg->path);
|
yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, $2->name, importpkg->path);
|
||||||
importpkg->direct = 1;
|
importpkg->direct = 1;
|
||||||
|
|
||||||
if(safemode && !curio.importsafe)
|
if(safemode && !curio.importsafe)
|
||||||
yyerror("cannot import unsafe package %Z", importpkg->path);
|
yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
import_safety:
|
import_safety:
|
||||||
@ -1686,7 +1686,11 @@ hidden_import:
|
|||||||
p->name = $2->name;
|
p->name = $2->name;
|
||||||
pkglookup($2->name, nil)->npkg++;
|
pkglookup($2->name, nil)->npkg++;
|
||||||
} else if(strcmp(p->name, $2->name) != 0)
|
} else if(strcmp(p->name, $2->name) != 0)
|
||||||
yyerror("conflicting names %s and %s for package %Z", p->name, $2->name, p->path);
|
yyerror("conflicting names %s and %s for package \"%Z\"", p->name, $2->name, p->path);
|
||||||
|
if(!incannedimport && myimportpath != nil && strcmp($3.u.sval->s, myimportpath) == 0) {
|
||||||
|
yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, $3.u.sval);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
| LVAR hidden_pkg_importsym hidden_type ';'
|
| LVAR hidden_pkg_importsym hidden_type ';'
|
||||||
{
|
{
|
||||||
|
@ -88,6 +88,7 @@ usage(void)
|
|||||||
print(" -h panic on an error\n");
|
print(" -h panic on an error\n");
|
||||||
print(" -m print about moves to heap\n");
|
print(" -m print about moves to heap\n");
|
||||||
print(" -o file specify output file\n");
|
print(" -o file specify output file\n");
|
||||||
|
print(" -p assumed import path for this code\n");
|
||||||
print(" -s disable escape analysis\n");
|
print(" -s disable escape analysis\n");
|
||||||
print(" -u disable package unsafe\n");
|
print(" -u disable package unsafe\n");
|
||||||
print(" -w print the parse tree after typing\n");
|
print(" -w print the parse tree after typing\n");
|
||||||
@ -154,6 +155,10 @@ main(int argc, char *argv[])
|
|||||||
case 'o':
|
case 'o':
|
||||||
outfile = EARGF(usage());
|
outfile = EARGF(usage());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
myimportpath = EARGF(usage());
|
||||||
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
addidir(EARGF(usage()));
|
addidir(EARGF(usage()));
|
||||||
@ -479,6 +484,11 @@ importfile(Val *f, int line)
|
|||||||
errorexit();
|
errorexit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(myimportpath != nil && strcmp(f->u.sval->s, myimportpath) == 0) {
|
||||||
|
yyerror("import \"%Z\" while compiling that package (import cycle)", f->u.sval);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
|
||||||
if(strcmp(f->u.sval->s, "unsafe") == 0) {
|
if(strcmp(f->u.sval->s, "unsafe") == 0) {
|
||||||
if(safemode) {
|
if(safemode) {
|
||||||
yyerror("cannot import package unsafe");
|
yyerror("cannot import package unsafe");
|
||||||
@ -500,14 +510,14 @@ importfile(Val *f, int line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!findpkg(path)) {
|
if(!findpkg(path)) {
|
||||||
yyerror("can't find import: %Z", f->u.sval);
|
yyerror("can't find import: \"%Z\"", f->u.sval);
|
||||||
errorexit();
|
errorexit();
|
||||||
}
|
}
|
||||||
importpkg = mkpkg(path);
|
importpkg = mkpkg(path);
|
||||||
|
|
||||||
imp = Bopen(namebuf, OREAD);
|
imp = Bopen(namebuf, OREAD);
|
||||||
if(imp == nil) {
|
if(imp == nil) {
|
||||||
yyerror("can't open import: %Z: %r", f->u.sval);
|
yyerror("can't open import: \"%Z\": %r", f->u.sval);
|
||||||
errorexit();
|
errorexit();
|
||||||
}
|
}
|
||||||
file = strdup(namebuf);
|
file = strdup(namebuf);
|
||||||
@ -564,7 +574,7 @@ importfile(Val *f, int line)
|
|||||||
continue;
|
continue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yyerror("no import in: %Z", f->u.sval);
|
yyerror("no import in \"%Z\"", f->u.sval);
|
||||||
unimportfile();
|
unimportfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1938,7 +1948,7 @@ mkpackage(char* pkgname)
|
|||||||
// errors if a conflicting top-level name is
|
// errors if a conflicting top-level name is
|
||||||
// introduced by a different file.
|
// introduced by a different file.
|
||||||
if(!s->def->used && !nsyntaxerrors)
|
if(!s->def->used && !nsyntaxerrors)
|
||||||
yyerrorl(s->def->lineno, "imported and not used: %Z", s->def->pkg->path);
|
yyerrorl(s->def->lineno, "imported and not used: \"%Z\"", s->def->pkg->path);
|
||||||
s->def = N;
|
s->def = N;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1946,7 +1956,7 @@ mkpackage(char* pkgname)
|
|||||||
// throw away top-level name left over
|
// throw away top-level name left over
|
||||||
// from previous import . "x"
|
// from previous import . "x"
|
||||||
if(s->def->pack != N && !s->def->pack->used && !nsyntaxerrors) {
|
if(s->def->pack != N && !s->def->pack->used && !nsyntaxerrors) {
|
||||||
yyerrorl(s->def->pack->lineno, "imported and not used: %Z", s->def->pack->pkg->path);
|
yyerrorl(s->def->pack->lineno, "imported and not used: \"%Z\"", s->def->pack->pkg->path);
|
||||||
s->def->pack->used = 1;
|
s->def->pack->used = 1;
|
||||||
}
|
}
|
||||||
s->def = N;
|
s->def = N;
|
||||||
|
@ -405,7 +405,7 @@ importdot(Pkg *opkg, Node *pack)
|
|||||||
}
|
}
|
||||||
if(n == 0) {
|
if(n == 0) {
|
||||||
// can't possibly be used - there were no symbols
|
// can't possibly be used - there were no symbols
|
||||||
yyerrorl(pack->lineno, "imported and not used: %Z", opkg->path);
|
yyerrorl(pack->lineno, "imported and not used: \"%Z\"", opkg->path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user