go/gcimporter: fix importing of anonymous interfaces
This is a backport of https://go-review.googlesource.com/#/c/41198/. For golang/go#20046. Change-Id: I58448c7dcc5e835d5c774e253cb56fec6e154f12 Reviewed-on: https://go-review.googlesource.com/41204 Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
a17c85b5d7
commit
c853fd5769
|
|
@ -31,6 +31,7 @@ type importer struct {
|
||||||
strList []string // in order of appearance
|
strList []string // in order of appearance
|
||||||
pkgList []*types.Package // in order of appearance
|
pkgList []*types.Package // in order of appearance
|
||||||
typList []types.Type // in order of appearance
|
typList []types.Type // in order of appearance
|
||||||
|
interfaceList []*types.Interface // for delayed completion only
|
||||||
trackAllTypes bool
|
trackAllTypes bool
|
||||||
|
|
||||||
// position encoding
|
// position encoding
|
||||||
|
|
@ -49,12 +50,13 @@ type importer struct {
|
||||||
// and returns the number of bytes consumed and a reference to the package.
|
// 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
|
// If the export data version is not recognized or the format is otherwise
|
||||||
// compromised, an error is returned.
|
// 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
|
// catch panics and return them as errors
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
// The package (filename) causing the problem is added to this
|
// The package (filename) causing the problem is added to this
|
||||||
// error by a wrapper in the caller (Import in gcimporter.go).
|
// 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)
|
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...)
|
p.typList = append(p.typList, predeclared...)
|
||||||
|
|
||||||
// read package data
|
// read package data
|
||||||
pkg := p.pkg()
|
pkg = p.pkg()
|
||||||
|
|
||||||
// read objects of phase 1 only (see cmd/compiler/internal/gc/bexport.go)
|
// read objects of phase 1 only (see cmd/compiler/internal/gc/bexport.go)
|
||||||
objcount := 0
|
objcount := 0
|
||||||
|
|
@ -140,15 +142,9 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
||||||
// ignore compiler-specific import data
|
// ignore compiler-specific import data
|
||||||
|
|
||||||
// complete interfaces
|
// complete interfaces
|
||||||
for _, typ := range p.typList {
|
// TODO(gri) re-investigate if we still need to do this in a delayed fashion
|
||||||
// If we only record named types (!p.trackAllTypes),
|
for _, typ := range p.interfaceList {
|
||||||
// we must check the underlying types here. If we
|
typ.Complete()
|
||||||
// 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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// record all referenced packages as imports
|
// 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)
|
t := types.NewInterface(p.methodList(parent), embeddeds)
|
||||||
|
p.interfaceList = append(p.interfaceList, t)
|
||||||
if p.trackAllTypes {
|
if p.trackAllTypes {
|
||||||
p.typList[n] = t
|
p.typList[n] = t
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,6 @@ func TestImportTestdata(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if outFn := compile(t, "testdata", testfile); outFn != "" {
|
if outFn := compile(t, "testdata", testfile); outFn != "" {
|
||||||
|
|
@ -168,7 +167,6 @@ func TestVersionHandling(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const dir = "./testdata/versions"
|
const dir = "./testdata/versions"
|
||||||
|
|
@ -232,7 +230,6 @@ func TestImportStdLib(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dt := maxTime
|
dt := maxTime
|
||||||
|
|
@ -263,7 +260,6 @@ func TestImportedTypes(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range importedObjectTests {
|
for _, test := range importedObjectTests {
|
||||||
|
|
@ -299,13 +295,9 @@ func TestIssue5815(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg, err := Import(make(map[string]*types.Package), "strings", ".")
|
pkg := importPkg(t, "strings")
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
scope := pkg.Scope()
|
scope := pkg.Scope()
|
||||||
for _, name := range scope.Names() {
|
for _, name := range scope.Names() {
|
||||||
|
|
@ -332,7 +324,6 @@ func TestCorrectMethodPackage(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
imports := make(map[string]*types.Package)
|
imports := make(map[string]*types.Package)
|
||||||
|
|
@ -356,7 +347,6 @@ func TestIssue13566(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
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
|
// 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)
|
// import must succeed (test for issue at hand)
|
||||||
pkg, err := Import(make(map[string]*types.Package), "./testdata/b", ".")
|
pkg := importPkg(t, "./testdata/b")
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure all indirectly imported packages have names
|
// make sure all indirectly imported packages have names
|
||||||
for _, imp := range pkg.Imports() {
|
for _, imp := range pkg.Imports() {
|
||||||
|
|
@ -392,7 +379,6 @@ func TestIssue13898(t *testing.T) {
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// import go/internal/gcimporter which imports go/types partially
|
// import go/internal/gcimporter which imports go/types partially
|
||||||
|
|
@ -415,10 +401,7 @@ func TestIssue13898(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for go/types.Object type
|
// look for go/types.Object type
|
||||||
obj := goTypesPkg.Scope().Lookup("Object")
|
obj := lookupObj(t, goTypesPkg.Scope(), "Object")
|
||||||
if obj == nil {
|
|
||||||
t.Fatal("go/types.Object not found")
|
|
||||||
}
|
|
||||||
typ, ok := obj.Type().(*types.Named)
|
typ, ok := obj.Type().(*types.Named)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("go/types.Object type is %v; wanted named type", typ)
|
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.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
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
|
// 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.
|
// This package only handles gc export data.
|
||||||
if runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
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
|
// 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)
|
defer os.Remove(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
imports := make(map[string]*types.Package)
|
importPkg(t, "./testdata/issue15920")
|
||||||
if _, err := Import(imports, "./testdata/issue15920", "."); err != nil {
|
}
|
||||||
|
|
||||||
|
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)
|
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue