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":
|
||||
wordSize = 4
|
||||
}
|
||||
cfg.TypeChecker.Sizes = &types.StdSizes{
|
||||
sizes := &types.StdSizes{
|
||||
MaxAlign: 8,
|
||||
WordSize: wordSize,
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ func doMain() error {
|
|||
// Run first main package.
|
||||
for _, main := range ssautil.MainPackages(pkgs) {
|
||||
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")
|
||||
}
|
||||
|
|
|
@ -124,22 +124,6 @@ type Config struct {
|
|||
// In build systems with explicit names for tests,
|
||||
// setting Tests may have no effect.
|
||||
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
|
||||
|
@ -361,10 +345,11 @@ func (p *Package) String() string { return p.ID }
|
|||
// loaderPackage augments Package with state used during the loading phase
|
||||
type loaderPackage struct {
|
||||
*Package
|
||||
importErrors map[string]error // maps each bad import to its error
|
||||
loadOnce sync.Once
|
||||
color uint8 // for cycle detection
|
||||
mark, needsrc bool // used when Mode >= LoadTypes
|
||||
importErrors map[string]error // maps each bad import to its error
|
||||
loadOnce sync.Once
|
||||
color uint8 // for cycle detection
|
||||
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.
|
||||
|
@ -435,6 +420,7 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
|
|||
ld.pkgs[lpkg.ID] = lpkg
|
||||
if isRoot[lpkg.ID] {
|
||||
initial = append(initial, lpkg)
|
||||
lpkg.initial = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,9 +590,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
|||
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
||||
}
|
||||
|
||||
// Copy the prototype types.Config as it must vary across Packages.
|
||||
tc := ld.TypeChecker // copy
|
||||
tc.Importer = importerFunc(func(path string) (*types.Package, error) {
|
||||
importer := importerFunc(func(path string) (*types.Package, error) {
|
||||
if path == "unsafe" {
|
||||
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)
|
||||
panic("unreachable")
|
||||
})
|
||||
tc.Error = appendError
|
||||
|
||||
// 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
|
||||
|
||||
|
|
Loading…
Reference in New Issue