go/packages: opt: ignore function bodies in non-initial packages
This saves 35% of wall time in a command such as $ gopackages -mode=syntax golang.org/x/tools/go/packages/gopackages fmt that would otherwise typecheck every function in each package that depends on fmt. It also applies in -mode=types when source was loaded as a fall back for missing export data due to an error in a lower package. Also, remove Config.TypeChecker field now that not a single of its subfields is passed through go/packages to the type checker. (The Sizes function is logically a result, not an input, of loading, though we have yet to implement it properly.) Change-Id: I472d21b34fc5e2832f7353e82992a67a06e4e4cc Reviewed-on: https://go-review.googlesource.com/129497 Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
8f8fd1f239
commit
9de1900191
|
@ -86,7 +86,7 @@ func doMain() error {
|
||||||
case "386", "arm":
|
case "386", "arm":
|
||||||
wordSize = 4
|
wordSize = 4
|
||||||
}
|
}
|
||||||
cfg.TypeChecker.Sizes = &types.StdSizes{
|
sizes := &types.StdSizes{
|
||||||
MaxAlign: 8,
|
MaxAlign: 8,
|
||||||
WordSize: wordSize,
|
WordSize: wordSize,
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ func doMain() error {
|
||||||
// Run first main package.
|
// Run first main package.
|
||||||
for _, main := range ssautil.MainPackages(pkgs) {
|
for _, main := range ssautil.MainPackages(pkgs) {
|
||||||
fmt.Fprintf(os.Stderr, "Running: %s\n", main.Pkg.Path())
|
fmt.Fprintf(os.Stderr, "Running: %s\n", main.Pkg.Path())
|
||||||
os.Exit(interp.Interpret(main, interpMode, cfg.TypeChecker.Sizes, main.Pkg.Path(), args))
|
os.Exit(interp.Interpret(main, interpMode, sizes, main.Pkg.Path(), args))
|
||||||
}
|
}
|
||||||
return fmt.Errorf("no main package")
|
return fmt.Errorf("no main package")
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,22 +124,6 @@ type Config struct {
|
||||||
// In build systems with explicit names for tests,
|
// In build systems with explicit names for tests,
|
||||||
// setting Tests may have no effect.
|
// setting Tests may have no effect.
|
||||||
Tests bool
|
Tests bool
|
||||||
|
|
||||||
// TypeChecker provides additional configuration for type-checking syntax trees.
|
|
||||||
//
|
|
||||||
// It is used for all packages in LoadAllSyntax mode,
|
|
||||||
// and for the packages matching the patterns, but not their dependencies,
|
|
||||||
// in LoadSyntax mode.
|
|
||||||
//
|
|
||||||
// The TypeChecker.Error function is ignored:
|
|
||||||
// errors are reported using the Error function defined above.
|
|
||||||
//
|
|
||||||
// The TypeChecker.Importer function is ignored:
|
|
||||||
// the loader defines an appropriate importer.
|
|
||||||
//
|
|
||||||
// TODO(rsc): TypeChecker.Sizes should use the same sizes as the main build.
|
|
||||||
// Derive them from the runtime?
|
|
||||||
TypeChecker types.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// driver is the type for functions that query the build system for the
|
// driver is the type for functions that query the build system for the
|
||||||
|
@ -361,10 +345,11 @@ func (p *Package) String() string { return p.ID }
|
||||||
// loaderPackage augments Package with state used during the loading phase
|
// loaderPackage augments Package with state used during the loading phase
|
||||||
type loaderPackage struct {
|
type loaderPackage struct {
|
||||||
*Package
|
*Package
|
||||||
importErrors map[string]error // maps each bad import to its error
|
importErrors map[string]error // maps each bad import to its error
|
||||||
loadOnce sync.Once
|
loadOnce sync.Once
|
||||||
color uint8 // for cycle detection
|
color uint8 // for cycle detection
|
||||||
mark, needsrc bool // used when Mode >= LoadTypes
|
needsrc bool // load from source (Mode >= LoadTypes)
|
||||||
|
initial bool // package was matched by a pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
// loader holds the working state of a single call to load.
|
// loader holds the working state of a single call to load.
|
||||||
|
@ -435,6 +420,7 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
|
||||||
ld.pkgs[lpkg.ID] = lpkg
|
ld.pkgs[lpkg.ID] = lpkg
|
||||||
if isRoot[lpkg.ID] {
|
if isRoot[lpkg.ID] {
|
||||||
initial = append(initial, lpkg)
|
initial = append(initial, lpkg)
|
||||||
|
lpkg.initial = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,9 +590,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
||||||
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the prototype types.Config as it must vary across Packages.
|
importer := importerFunc(func(path string) (*types.Package, error) {
|
||||||
tc := ld.TypeChecker // copy
|
|
||||||
tc.Importer = importerFunc(func(path string) (*types.Package, error) {
|
|
||||||
if path == "unsafe" {
|
if path == "unsafe" {
|
||||||
return types.Unsafe, nil
|
return types.Unsafe, nil
|
||||||
}
|
}
|
||||||
|
@ -630,10 +614,22 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
||||||
log.Fatalf("internal error: nil Pkg importing %q from %q", path, lpkg)
|
log.Fatalf("internal error: nil Pkg importing %q from %q", path, lpkg)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
})
|
})
|
||||||
tc.Error = appendError
|
|
||||||
|
|
||||||
// type-check
|
// type-check
|
||||||
types.NewChecker(&tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
|
tc := &types.Config{
|
||||||
|
Importer: importer,
|
||||||
|
|
||||||
|
// Type-check bodies of functions only in non-initial packages.
|
||||||
|
// Example: for import graph A->B->C and initial packages {A,C},
|
||||||
|
// we can ignore function bodies in B.
|
||||||
|
IgnoreFuncBodies: ld.Mode < LoadAllSyntax && !lpkg.initial,
|
||||||
|
|
||||||
|
Error: appendError,
|
||||||
|
|
||||||
|
// TODO(adonovan): derive Sizes from the underlying
|
||||||
|
// build system.
|
||||||
|
}
|
||||||
|
types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
|
||||||
|
|
||||||
lpkg.importErrors = nil // no longer needed
|
lpkg.importErrors = nil // no longer needed
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue