go/gcimporter15: backport double-export fix for aliased objects
Backport of https://golang.org/cl/32575.
Change-Id: Ic4b0794ee440b7ac6275f0ef7dacda20de4fdad0
Reviewed-on: https://go-review.googlesource.com/32577
Reviewed-by: Alan Donovan <adonovan@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/go/gcimporter15/bexport.go b/go/gcimporter15/bexport.go
index 39f6ce3..f7615ba 100644
--- a/go/gcimporter15/bexport.go
+++ b/go/gcimporter15/bexport.go
@@ -63,6 +63,9 @@
pkgIndex map[*types.Package]int
typIndex map[types.Type]int
+ // track objects that we've reexported already
+ reexported map[types.Object]bool
+
// position encoding
posInfoFormat bool
prevFile string
@@ -81,6 +84,7 @@
strIndex: map[string]int{"": 0}, // empty string is mapped to 0
pkgIndex: make(map[*types.Package]int),
typIndex: make(map[types.Type]int),
+ reexported: make(map[types.Object]bool),
posInfoFormat: true, // TODO(gri) might become a flag, eventually
}
@@ -178,10 +182,17 @@
// invalid alias - don't export for now (issue 17731)
return
}
+
+ if !p.reexported[orig] {
+ p.obj(orig)
+ p.reexported[orig] = true
+ }
+
p.tag(aliasTag)
p.pos(obj)
p.string(obj.Name())
- obj = orig
+ p.qualifiedName(orig)
+ return
}
switch obj := obj.(type) {
diff --git a/go/gcimporter15/bimport.go b/go/gcimporter15/bimport.go
index 9bd9eb7..8e9a6b2 100644
--- a/go/gcimporter15/bimport.go
+++ b/go/gcimporter15/bimport.go
@@ -225,10 +225,11 @@
return funcTag
// Aliases are not exported multiple times, thus we should not see them here.
default:
- errorf("unexpected object: %v (%T)", obj, obj)
+ errorf("unexpected object: %v (%T)", obj, obj) // panics
panic("unreachable")
}
}
+
func sameObj(a, b types.Object) bool {
// Because unnamed types are not canonicalized, we cannot simply compare types for
// (pointer) identity.
@@ -236,7 +237,7 @@
return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
}
-func (p *importer) declare(obj types.Object) types.Object {
+func (p *importer) declare(obj types.Object) {
pkg := obj.Pkg()
if alt := pkg.Scope().Insert(obj); alt != nil {
// This can only trigger if we import a (non-type) object a second time.
@@ -244,48 +245,33 @@
// once; and b) we ignore compiler-specific export data which may contain
// functions whose inlined function bodies refer to other functions that
// were already imported.
- // However, if a package exports multiple aliases referring to the same
- // original object, that object is currently exported multiple times.
- // Check for that specific case and accept it if the aliases correspond
- // (see also the comment in cmd/compile/internal/gc/bimport.go, method
- // importer.obj, switch case importing functions).
+ // However, aliases require reexporting the original object, so we need
+ // to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
+ // method importer.obj, switch case importing functions).
// Note that the original itself cannot be an alias.
- // TODO(gri) We can avoid doing this once objects are exported only once
- // per package again (issue #17636).
if !sameObj(obj, alt) {
- errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", alt, obj)
+ errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
}
- obj = alt // use object that was imported first
}
- return obj
}
func (p *importer) obj(tag int) {
- var aliasPos token.Pos
- var aliasName string
- if tag == aliasTag {
- aliasPos = p.pos()
- aliasName = p.string()
- tag = p.tagOrIndex()
- }
-
- var obj types.Object
switch tag {
case constTag:
pos := p.pos()
pkg, name := p.qualifiedName()
typ := p.typ(nil)
val := p.value()
- obj = p.declare(types.NewConst(pos, pkg, name, typ, val))
+ p.declare(types.NewConst(pos, pkg, name, typ, val))
case typeTag:
- obj = p.typ(nil).(*types.Named).Obj()
+ p.typ(nil)
case varTag:
pos := p.pos()
pkg, name := p.qualifiedName()
typ := p.typ(nil)
- obj = p.declare(types.NewVar(pos, pkg, name, typ))
+ p.declare(types.NewVar(pos, pkg, name, typ))
case funcTag:
pos := p.pos()
@@ -293,15 +279,18 @@
params, isddd := p.paramList()
result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd)
- obj = p.declare(types.NewFunc(pos, pkg, name, sig))
+ p.declare(types.NewFunc(pos, pkg, name, sig))
+
+ case aliasTag:
+ aliasPos := p.pos()
+ aliasName := p.string()
+ pkg, name := p.qualifiedName()
+ obj := pkg.Scope().Lookup(name)
+ p.declare(newAlias(aliasPos, p.pkgList[0], aliasName,obj))
default:
errorf("unexpected object tag %d", tag)
}
-
- if aliasName != "" {
- p.declare(newAlias(aliasPos, p.pkgList[0], aliasName, obj))
- }
}
func (p *importer) pos() token.Pos {
@@ -553,7 +542,7 @@
return t
default:
- errorf("unexpected type tag %d", i)
+ errorf("unexpected type tag %d", i) // panics
panic("unreachable")
}
}
@@ -704,7 +693,7 @@
case unknownTag:
return constant.MakeUnknown()
default:
- errorf("unexpected value tag %d", tag)
+ errorf("unexpected value tag %d", tag) // panics
panic("unreachable")
}
}
diff --git a/go/gcimporter15/newalias18.go b/go/gcimporter15/newalias18.go
index 446a038..ff4d535 100644
--- a/go/gcimporter15/newalias18.go
+++ b/go/gcimporter15/newalias18.go
@@ -12,8 +12,8 @@
// TODO(gri) Consider exporting this functionality from go/types (issue 17730).
func original(obj types.Object) types.Object {
- if orig, ok := obj.(*types.Alias); ok {
- return orig
+ if alias, ok := obj.(*types.Alias); ok {
+ return alias.Orig()
}
return obj
}