go/gcimporter15: pretend blank fields have same owner

The export data formats (text and binary) emitted by gc in Go 1.7 did
not record the package that "owns" each blank field, even though blank
is an unexported identifier.  Before, gcimporter would assume the
package of the export data file owns blank fields within it, even
blank fields reexported from another package.  As a result, identical
types would become nonidentical during reexporting.

For bug compatibility with gc, gcimporter now treats blank fields as
if they all belong to the same dummy package, avoiding spurious "can't
assign A to B" errors in tools based on go/types.

Change-Id: I0dbf71491a0ec0f376e9dc8a91efe0376c855a28
Reviewed-on: https://go-review.googlesource.com/33146
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/go/gcimporter15/bimport.go b/go/gcimporter15/bimport.go
index e0ca8c9..ce4b687 100644
--- a/go/gcimporter15/bimport.go
+++ b/go/gcimporter15/bimport.go
@@ -616,6 +616,20 @@
 	}
 	if p.version == 0 && name == "_" {
 		// version 0 didn't export a package for _ fields
+		// see issue #15514
+
+		// For bug-compatibility with gc, pretend all imported
+		// blank fields belong to the same dummy package.
+		// This avoids spurious "cannot assign A to B" errors
+		// from go/types caused by types changing as they are
+		// re-exported.
+		const blankpkg = "<_>"
+		pkg := p.imports[blankpkg]
+		if pkg == nil {
+			pkg = types.NewPackage(blankpkg, blankpkg)
+			p.imports[blankpkg] = pkg
+		}
+
 		return pkg, name
 	}
 	if name != "" && !exported(name) {
diff --git a/go/gcimporter15/gcimporter.go b/go/gcimporter15/gcimporter.go
index 48a4ef2..6fbc9d7 100644
--- a/go/gcimporter15/gcimporter.go
+++ b/go/gcimporter15/gcimporter.go
@@ -500,6 +500,19 @@
 //
 func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
 	pkg, name := p.parseName(parent, true)
+
+	if name == "_" {
+		// Blank fields should be package-qualified because they
+		// are unexported identifiers, but gc does not qualify them.
+		// Assuming that the ident belongs to the current package
+		// causes types to change during re-exporting, leading
+		// to spurious "can't assign A to B" errors from go/types.
+		// As a workaround, pretend all blank fields belong
+		// to the same unique dummy package.
+		const blankpkg = "<_>"
+		pkg = p.getPkg(blankpkg, blankpkg)
+	}
+
 	typ := p.parseType(parent)
 	anonymous := false
 	if name == "" {