diff --git a/go/gcimporter15/bexport.go b/go/gcimporter15/bexport.go index 39f6ce39..f7615ba4 100644 --- a/go/gcimporter15/bexport.go +++ b/go/gcimporter15/bexport.go @@ -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) { diff --git a/go/gcimporter15/bimport.go b/go/gcimporter15/bimport.go index 9bd9eb78..8e9a6b28 100644 --- a/go/gcimporter15/bimport.go +++ b/go/gcimporter15/bimport.go @@ -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") } } diff --git a/go/gcimporter15/newalias18.go b/go/gcimporter15/newalias18.go index 446a0388..ff4d5354 100644 --- a/go/gcimporter15/newalias18.go +++ b/go/gcimporter15/newalias18.go @@ -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 }