diff --git a/go/gcimporter15/bimport.go b/go/gcimporter15/bimport.go index 3bec19c1..369dfb65 100644 --- a/go/gcimporter15/bimport.go +++ b/go/gcimporter15/bimport.go @@ -28,9 +28,10 @@ type importer struct { version int // export format version // object lists - strList []string // in order of appearance - pkgList []*types.Package // in order of appearance - typList []types.Type // in order of appearance + strList []string // in order of appearance + pkgList []*types.Package // in order of appearance + typList []types.Type // in order of appearance + interfaceList []*types.Interface // for delayed completion only trackAllTypes bool // position encoding @@ -49,12 +50,13 @@ type importer struct { // and returns the number of bytes consumed and a reference to the package. // If the export data version is not recognized or the format is otherwise // compromised, an error is returned. -func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, _ *types.Package, err error) { +func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { // catch panics and return them as errors defer func() { if e := recover(); e != nil { // The package (filename) causing the problem is added to this // error by a wrapper in the caller (Import in gcimporter.go). + // Return a (possibly nil or incomplete) package unchanged (see #16088). err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e) } }() @@ -119,7 +121,7 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data [] p.typList = append(p.typList, predeclared...) // read package data - pkg := p.pkg() + pkg = p.pkg() // read objects of phase 1 only (see cmd/compiler/internal/gc/bexport.go) objcount := 0 @@ -140,15 +142,9 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data [] // ignore compiler-specific import data // complete interfaces - for _, typ := range p.typList { - // If we only record named types (!p.trackAllTypes), - // we must check the underlying types here. If we - // track all types, the Underlying() method call is - // not needed. - // TODO(gri) Remove if p.trackAllTypes is gone. - if it, ok := typ.Underlying().(*types.Interface); ok { - it.Complete() - } + // TODO(gri) re-investigate if we still need to do this in a delayed fashion + for _, typ := range p.interfaceList { + typ.Complete() } // record all referenced packages as imports @@ -500,6 +496,7 @@ func (p *importer) typ(parent *types.Package) types.Type { } t := types.NewInterface(p.methodList(parent), embeddeds) + p.interfaceList = append(p.interfaceList, t) if p.trackAllTypes { p.typList[n] = t } diff --git a/go/gcimporter15/gcimporter_test.go b/go/gcimporter15/gcimporter_test.go index d63f1122..56cdfc04 100644 --- a/go/gcimporter15/gcimporter_test.go +++ b/go/gcimporter15/gcimporter_test.go @@ -134,7 +134,6 @@ func TestImportTestdata(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } if outFn := compile(t, "testdata", testfile); outFn != "" { @@ -168,7 +167,6 @@ func TestVersionHandling(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } const dir = "./testdata/versions" @@ -232,7 +230,6 @@ func TestImportStdLib(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } dt := maxTime @@ -263,7 +260,6 @@ func TestImportedTypes(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } for _, test := range importedObjectTests { @@ -299,13 +295,9 @@ func TestIssue5815(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } - pkg, err := Import(make(map[string]*types.Package), "strings", ".") - if err != nil { - t.Fatal(err) - } + pkg := importPkg(t, "strings") scope := pkg.Scope() for _, name := range scope.Names() { @@ -332,7 +324,6 @@ func TestCorrectMethodPackage(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } imports := make(map[string]*types.Package) @@ -356,7 +347,6 @@ func TestIssue13566(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } // On windows, we have to set the -D option for the compiler to avoid having a drive @@ -373,10 +363,7 @@ func TestIssue13566(t *testing.T) { } // import must succeed (test for issue at hand) - pkg, err := Import(make(map[string]*types.Package), "./testdata/b", ".") - if err != nil { - t.Fatal(err) - } + pkg := importPkg(t, "./testdata/b") // make sure all indirectly imported packages have names for _, imp := range pkg.Imports() { @@ -392,7 +379,6 @@ func TestIssue13898(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } // import go/internal/gcimporter which imports go/types partially @@ -415,10 +401,7 @@ func TestIssue13898(t *testing.T) { } // look for go/types.Object type - obj := goTypesPkg.Scope().Lookup("Object") - if obj == nil { - t.Fatal("go/types.Object not found") - } + obj := lookupObj(t, goTypesPkg.Scope(), "Object") typ, ok := obj.Type().(*types.Named) if !ok { t.Fatalf("go/types.Object type is %v; wanted named type", typ) @@ -442,7 +425,6 @@ func TestIssue15517(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } // On windows, we have to set the -D option for the compiler to avoid having a drive @@ -481,7 +463,6 @@ func TestIssue15920(t *testing.T) { // This package only handles gc export data. if runtime.Compiler != "gc" { t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - return } // On windows, we have to set the -D option for the compiler to avoid having a drive @@ -494,8 +475,47 @@ func TestIssue15920(t *testing.T) { defer os.Remove(f) } - imports := make(map[string]*types.Package) - if _, err := Import(imports, "./testdata/issue15920", "."); err != nil { - t.Fatal(err) + importPkg(t, "./testdata/issue15920") +} + +func TestIssue20046(t *testing.T) { + skipSpecialPlatforms(t) + + // This package only handles gc export data. + if runtime.Compiler != "gc" { + t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) + } + + // On windows, we have to set the -D option for the compiler to avoid having a drive + // letter and an illegal ':' in the import path - just skip it (see also issue #3483). + if runtime.GOOS == "windows" { + t.Skip("avoid dealing with relative paths/drive letters on windows") + } + + if f := compile(t, "testdata", "issue20046.go"); f != "" { + defer os.Remove(f) + } + + // "./issue20046".V.M must exist + pkg := importPkg(t, "./testdata/issue20046") + obj := lookupObj(t, pkg.Scope(), "V") + if m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, "M"); m == nil { + t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect) } } + +func importPkg(t *testing.T, path string) *types.Package { + pkg, err := Import(make(map[string]*types.Package), path, ".") + if err != nil { + t.Fatal(err) + } + return pkg +} + +func lookupObj(t *testing.T, scope *types.Scope, name string) types.Object { + if obj := scope.Lookup(name); obj != nil { + return obj + } + t.Fatalf("%s not found", name) + return nil +} diff --git a/go/gcimporter15/testdata/issue20046.go b/go/gcimporter15/testdata/issue20046.go new file mode 100644 index 00000000..c63ee821 --- /dev/null +++ b/go/gcimporter15/testdata/issue20046.go @@ -0,0 +1,9 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +var V interface { + M() +}