Skip to content

Commit 0d47e24

Browse files
committed
go/packages: allow types loading without NeedDeps
Before separating Load* into Need* we could use LoadSyntax to get types information by loading inital packages from source code and loading it's direct dependencies from export data. It was broken when separation was introduced and before this commit everything was loading from source code what resulted into slow loading times. This commit fixes it. Also, do backwards-incompatible fix of definition of deprecated LoadImports and LoadAllSyntax. Improve an internal error message "internal error: nil Pkg importing x from y": replace it with "internal error: package x without types was imported from y". Remove packages.NeedDeps request for loading in tests TestLoadTypesBits and TestContainsOverlayXTest. Fixes golang/go#31752, fixes #golang/go#33077
1 parent 8b92790 commit 0d47e24

File tree

3 files changed

+83
-25
lines changed

3 files changed

+83
-25
lines changed

go/packages/golist.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ func golistargs(cfg *Config, words []string) []string {
733733
fmt.Sprintf("-compiled=%t", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypesInfo|NeedTypesSizes) != 0),
734734
fmt.Sprintf("-test=%t", cfg.Tests),
735735
fmt.Sprintf("-export=%t", usesExportData(cfg)),
736-
fmt.Sprintf("-deps=%t", cfg.Mode&NeedDeps != 0),
736+
fmt.Sprintf("-deps=%t", cfg.Mode&NeedImports != 0),
737737
// go list doesn't let you pass -test and -find together,
738738
// probably because you'd just get the TestMain.
739739
fmt.Sprintf("-find=%t", !cfg.Tests && cfg.Mode&findFlags == 0),

go/packages/packages.go

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ const (
7575

7676
// Deprecated: LoadImports exists for historical compatibility
7777
// and should not be used. Please directly specify the needed fields using the Need values.
78-
LoadImports = LoadFiles | NeedImports | NeedDeps
78+
LoadImports = LoadFiles | NeedImports
7979

8080
// Deprecated: LoadTypes exists for historical compatibility
8181
// and should not be used. Please directly specify the needed fields using the Need values.
@@ -87,7 +87,7 @@ const (
8787

8888
// Deprecated: LoadAllSyntax exists for historical compatibility
8989
// and should not be used. Please directly specify the needed fields using the Need values.
90-
LoadAllSyntax = LoadSyntax
90+
LoadAllSyntax = LoadSyntax | NeedDeps
9191
)
9292

9393
// A Config specifies details about how packages should be loaded.
@@ -479,8 +479,8 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
479479
}
480480
lpkg := &loaderPackage{
481481
Package: pkg,
482-
needtypes: (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && rootIndex < 0) || rootIndex >= 0,
483-
needsrc: (ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && rootIndex < 0) || rootIndex >= 0 ||
482+
needtypes: (ld.Mode&(NeedTypes|NeedTypesInfo) != 0 && ld.Mode&NeedDeps != 0 && rootIndex < 0) || rootIndex >= 0,
483+
needsrc: (ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && ld.Mode&NeedDeps != 0 && rootIndex < 0) || rootIndex >= 0 ||
484484
len(ld.Overlay) > 0 || // Overlays can invalidate export data. TODO(matloob): make this check fine-grained based on dependencies on overlaid files
485485
pkg.ExportFile == "" && pkg.PkgPath != "unsafe",
486486
}
@@ -528,8 +528,7 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
528528
stack = append(stack, lpkg) // push
529529
stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports
530530
// If NeedImports isn't set, the imports fields will all be zeroed out.
531-
// If NeedDeps isn't also set we want to keep the stubs.
532-
if ld.Mode&NeedImports != 0 && ld.Mode&NeedDeps != 0 {
531+
if ld.Mode&NeedImports != 0 {
533532
lpkg.Imports = make(map[string]*Package, len(stubs))
534533
for importPath, ipkg := range stubs {
535534
var importErr error
@@ -577,7 +576,7 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
577576
visit(lpkg)
578577
}
579578
}
580-
if ld.Mode&NeedDeps != 0 { // TODO(matloob): This is only the case if NeedTypes is also set, right?
579+
if ld.Mode&NeedImports != 0 && ld.Mode&NeedTypes != 0 {
581580
for _, lpkg := range srcPkgs {
582581
// Complete type information is required for the
583582
// immediate dependencies of each source package.
@@ -602,7 +601,6 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
602601
}
603602

604603
result := make([]*Package, len(initial))
605-
importPlaceholders := make(map[string]*Package)
606604
for i, lpkg := range initial {
607605
result[i] = lpkg.Package
608606
}
@@ -639,16 +637,6 @@ func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
639637
if ld.Mode&NeedTypesSizes == 0 {
640638
ld.pkgs[i].TypesSizes = nil
641639
}
642-
if ld.Mode&NeedDeps == 0 {
643-
for j, pkg := range ld.pkgs[i].Imports {
644-
ph, ok := importPlaceholders[pkg.ID]
645-
if !ok {
646-
ph = &Package{ID: pkg.ID}
647-
importPlaceholders[pkg.ID] = ph
648-
}
649-
ld.pkgs[i].Imports[j] = ph
650-
}
651-
}
652640
}
653641
return result, nil
654642
}
@@ -670,7 +658,6 @@ func (ld *loader) loadRecursive(lpkg *loaderPackage) {
670658
}(imp)
671659
}
672660
wg.Wait()
673-
674661
ld.loadPackage(lpkg)
675662
})
676663
}
@@ -797,7 +784,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
797784
if ipkg.Types != nil && ipkg.Types.Complete() {
798785
return ipkg.Types, nil
799786
}
800-
log.Fatalf("internal error: nil Pkg importing %q from %q", path, lpkg)
787+
log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg)
801788
panic("unreachable")
802789
})
803790

@@ -808,7 +795,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
808795
// Type-check bodies of functions only in non-initial packages.
809796
// Example: for import graph A->B->C and initial packages {A,C},
810797
// we can ignore function bodies in B.
811-
IgnoreFuncBodies: (ld.Mode&(NeedDeps|NeedTypesInfo) == 0) && !lpkg.initial,
798+
IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,
812799

813800
Error: appendError,
814801
Sizes: ld.sizes,
@@ -1071,5 +1058,5 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
10711058
}
10721059

10731060
func usesExportData(cfg *Config) bool {
1074-
return cfg.Mode&NeedExportsFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedTypesInfo == 0
1061+
return cfg.Mode&NeedExportsFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0
10751062
}

go/packages/packages_test.go

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ func testLoadTypesBits(t *testing.T, exporter packagestest.Exporter) {
569569
}}})
570570
defer exported.Cleanup()
571571

572-
exported.Config.Mode = packages.NeedTypes | packages.NeedDeps | packages.NeedImports
572+
exported.Config.Mode = packages.NeedTypes | packages.NeedImports
573573
initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
574574
if err != nil {
575575
t.Fatal(err)
@@ -1236,7 +1236,7 @@ func testContainsOverlayXTest(t *testing.T, exporter packagestest.Exporter) {
12361236
}}})
12371237
defer exported.Cleanup()
12381238
bOverlayXTestFile := filepath.Join(filepath.Dir(exported.File("golang.org/fake", "b/b.go")), "b_overlay_x_test.go")
1239-
exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedImports | packages.NeedDeps
1239+
exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedImports
12401240
exported.Config.Overlay = map[string][]byte{bOverlayXTestFile: []byte(`package b_test; import "golang.org/fake/b"`)}
12411241
initial, err := packages.Load(exported.Config, "file="+bOverlayXTestFile)
12421242
if err != nil {
@@ -1928,6 +1928,77 @@ func testAdHocContains(t *testing.T, exporter packagestest.Exporter) {
19281928
}
19291929
}
19301930

1931+
func TestLoadTypesInfoWithoutNeedDeps(t *testing.T) {
1932+
packagestest.TestAll(t, testLoadTypesInfoWithoutNeedDeps)
1933+
}
1934+
func testLoadTypesInfoWithoutNeedDeps(t *testing.T, exporter packagestest.Exporter) {
1935+
exported := packagestest.Export(t, exporter, []packagestest.Module{{
1936+
Name: "golang.org/fake",
1937+
Files: map[string]interface{}{
1938+
"a/a.go": `package a; import _ "golang.org/fake/b"`,
1939+
"b/b.go": `package b`,
1940+
}}})
1941+
defer exported.Cleanup()
1942+
1943+
exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports
1944+
pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
1945+
if err != nil {
1946+
t.Fatal(err)
1947+
}
1948+
pkg := pkgs[0]
1949+
if pkg.IllTyped {
1950+
t.Fatal("Loaded package is ill typed")
1951+
}
1952+
const expectedImport = "golang.org/fake/b"
1953+
if _, ok := pkg.Imports[expectedImport]; !ok || len(pkg.Imports) != 1 {
1954+
t.Fatalf("Imports of loaded package: want [%s], got %v", expectedImport, pkg.Imports)
1955+
}
1956+
}
1957+
1958+
func TestLoadWithNeedDeps(t *testing.T) {
1959+
packagestest.TestAll(t, testLoadWithNeedDeps)
1960+
}
1961+
func testLoadWithNeedDeps(t *testing.T, exporter packagestest.Exporter) {
1962+
exported := packagestest.Export(t, exporter, []packagestest.Module{{
1963+
Name: "golang.org/fake",
1964+
Files: map[string]interface{}{
1965+
"a/a.go": `package a; import _ "golang.org/fake/b"`,
1966+
"b/b.go": `package b; import _ "golang.org/fake/c"`,
1967+
"c/c.go": `package c`,
1968+
}}})
1969+
defer exported.Cleanup()
1970+
1971+
exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports | packages.NeedDeps
1972+
pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
1973+
if err != nil {
1974+
t.Fatal(err)
1975+
}
1976+
if len(pkgs) != 1 {
1977+
t.Fatalf("Expected 1 package, got %d", len(pkgs))
1978+
}
1979+
1980+
pkgA := pkgs[0]
1981+
if pkgA.IllTyped {
1982+
t.Fatal("Loaded package is ill typed")
1983+
}
1984+
1985+
pkgB := pkgA.Imports["golang.org/fake/b"]
1986+
if pkgB == nil || len(pkgA.Imports) != 1 {
1987+
t.Fatalf("Imports of loaded package 'a' are invalid: %v", pkgA.Imports)
1988+
}
1989+
if pkgB.Types == nil || !pkgB.Types.Complete() || pkgB.TypesInfo == nil {
1990+
t.Fatalf("Types of package 'b' are nil or incomplete: %v, %v", pkgB.Types, pkgB.TypesInfo)
1991+
}
1992+
1993+
pkgC := pkgB.Imports["golang.org/fake/c"]
1994+
if pkgC == nil || len(pkgB.Imports) != 1 {
1995+
t.Fatalf("Imports of loaded package 'c' are invalid: %v", pkgB.Imports)
1996+
}
1997+
if pkgC.Types == nil || !pkgC.Types.Complete() || pkgC.TypesInfo == nil {
1998+
t.Fatalf("Types of package 'b' are nil or incomplete: %v, %v", pkgC.Types, pkgC.TypesInfo)
1999+
}
2000+
}
2001+
19312002
func errorMessages(errors []packages.Error) []string {
19322003
var msgs []string
19332004
for _, err := range errors {

0 commit comments

Comments
 (0)