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>
This commit is contained in:
parent
a829b5068d
commit
d4397e8931
|
|
@ -63,6 +63,9 @@ type exporter struct {
|
|||
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 @@ func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
|
|||
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 @@ func (p *exporter) obj(obj types.Object) {
|
|||
// 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) {
|
||||
|
|
|
|||
|
|
@ -225,10 +225,11 @@ func objTag(obj types.Object) int {
|
|||
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 @@ func sameObj(a, b types.Object) bool {
|
|||
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 @@ func (p *importer) declare(obj types.Object) types.Object {
|
|||
// 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 @@ func (p *importer) obj(tag int) {
|
|||
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 @@ func (p *importer) typ(parent *types.Package) types.Type {
|
|||
return t
|
||||
|
||||
default:
|
||||
errorf("unexpected type tag %d", i)
|
||||
errorf("unexpected type tag %d", i) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
|
@ -704,7 +693,7 @@ func (p *importer) value() constant.Value {
|
|||
case unknownTag:
|
||||
return constant.MakeUnknown()
|
||||
default:
|
||||
errorf("unexpected value tag %d", tag)
|
||||
errorf("unexpected value tag %d", tag) // panics
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ func newAlias => types.NewAlias
|
|||
|
||||
// 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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue