diff --git a/go/gcimporter15/bimport.go b/go/gcimporter15/bimport.go index 9fede043..b2af4b19 100644 --- a/go/gcimporter15/bimport.go +++ b/go/gcimporter15/bimport.go @@ -181,7 +181,7 @@ func (p *importer) declare(obj types.Object) { // imported. // (See also the comment in cmd/compile/internal/gc/bimport.go importer.obj, // switch case importing functions). - panic(fmt.Sprintf("%s already declared", alt.Name())) + panic(fmt.Sprintf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", alt, obj)) } } diff --git a/go/gcimporter15/gcimporter.go b/go/gcimporter15/gcimporter.go index 4416739b..7725b3ef 100644 --- a/go/gcimporter15/gcimporter.go +++ b/go/gcimporter15/gcimporter.go @@ -175,7 +175,7 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types data, err = ioutil.ReadAll(buf) if err == nil { fset := token.NewFileSet() - _, pkg, err = BImportData(fset, packages, data, path) + _, pkg, err = BImportData(fset, packages, data, id) return } default: diff --git a/go/gcimporter15/gcimporter_test.go b/go/gcimporter15/gcimporter_test.go index 873ef46e..4265516a 100644 --- a/go/gcimporter15/gcimporter_test.go +++ b/go/gcimporter15/gcimporter_test.go @@ -363,3 +363,42 @@ func TestIssue13898(t *testing.T) { t.Fatalf("found %v; want go/types", m.Pkg()) } } + +func TestIssue15517(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) + return + } + + // 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", "p.go"); f != "" { + defer os.Remove(f) + } + + // Multiple imports of p must succeed without redeclaration errors. + // We use an import path that's not cleaned up so that the eventual + // file path for the package is different from the package path; this + // will expose the error if it is present. + // + // (Issue: Both the textual and the binary importer used the file path + // of the package to be imported as key into the shared packages map. + // However, the binary importer then used the package path to identify + // the imported package to mark it as complete; effectively marking the + // wrong package as complete. By using an "unclean" package path, the + // file and package path are different, exposing the problem if present. + // The same issue occurs with vendoring.) + imports := make(map[string]*types.Package) + for i := 0; i < 3; i++ { + if _, err := Import(imports, "./././testdata/p", "."); err != nil { + t.Fatal(err) + } + } +} diff --git a/go/gcimporter15/testdata/p.go b/go/gcimporter15/testdata/p.go new file mode 100644 index 00000000..9e2e7057 --- /dev/null +++ b/go/gcimporter15/testdata/p.go @@ -0,0 +1,13 @@ +// Copyright 2016 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. + +// Input for TestIssue15517 + +package p + +const C = 0 + +var V int + +func F() {}