mirror of https://github.com/golang/go.git
[dev.go2go] go/go2go: instantiate embedded field when needed
If an embedded field is an instantiated type, we need to instantiate it when instantiating the whole type, in case the type arguments themselves need instantiation. Fixes #39953 Change-Id: I80b57456aa4f8e8b2eff82359066c37a9c2a40f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/240522 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
08b9fd164c
commit
938e96e732
|
|
@ -676,7 +676,22 @@ func (t *translator) instantiateExpr(ta *typeArgs, e ast.Expr) ast.Expr {
|
|||
}
|
||||
case *ast.SelectorExpr:
|
||||
x := t.instantiateExpr(ta, e.X)
|
||||
if x == e.X {
|
||||
|
||||
// If this is a reference to an instantiated embedded field,
|
||||
// we may need to instantiate it. The actual instantiation
|
||||
// is at the end of the function, as long as we create a
|
||||
// a new SelectorExpr when needed.
|
||||
instantiate := false
|
||||
obj := t.importer.info.ObjectOf(e.Sel)
|
||||
if obj != nil {
|
||||
if f, ok := obj.(*types.Var); ok && f.Embedded() {
|
||||
if named, ok := f.Type().(*types.Named); ok && len(named.TArgs()) > 0 && obj.Name() == named.Obj().Name() {
|
||||
instantiate = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if x == e.X && !instantiate {
|
||||
return e
|
||||
}
|
||||
r = &ast.SelectorExpr{
|
||||
|
|
|
|||
|
|
@ -794,7 +794,11 @@ func (t *translator) translateSelectorExpr(pe *ast.Expr) {
|
|||
// We have to rewrite the name to the name used in
|
||||
// the translated struct definition.
|
||||
if f, ok := obj.(*types.Var); ok && f.Embedded() {
|
||||
named, ok := f.Type().(*types.Named)
|
||||
typ := t.lookupType(e)
|
||||
if typ == nil {
|
||||
typ = f.Type()
|
||||
}
|
||||
named, ok := typ.(*types.Named)
|
||||
if !ok || len(named.TArgs()) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// compile
|
||||
|
||||
// Copyright 2020 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.
|
||||
|
||||
package p
|
||||
|
||||
type top(type T, T2) struct {
|
||||
p *parent(T, T2)
|
||||
}
|
||||
|
||||
type parent(type T, T2) struct {
|
||||
(child(T, T2))
|
||||
}
|
||||
|
||||
type child(type T, T2) struct {
|
||||
T2
|
||||
}
|
||||
|
||||
func (d *top(T, T2)) foo() *T {
|
||||
return d.p.child.foo()
|
||||
}
|
||||
|
||||
func (rb *child(T, T2)) foo() *T {
|
||||
return nil
|
||||
}
|
||||
|
||||
var V top(int, int)
|
||||
Loading…
Reference in New Issue