diff --git a/src/go/go2go/instantiate.go b/src/go/go2go/instantiate.go index 7055c23ded..791f435499 100644 --- a/src/go/go2go/instantiate.go +++ b/src/go/go2go/instantiate.go @@ -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{ diff --git a/src/go/go2go/rewrite.go b/src/go/go2go/rewrite.go index 2b3ef7cc3f..bf1e2aecb9 100644 --- a/src/go/go2go/rewrite.go +++ b/src/go/go2go/rewrite.go @@ -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 } diff --git a/test/gen/g039.go2 b/test/gen/g039.go2 new file mode 100644 index 0000000000..69ec25ad31 --- /dev/null +++ b/test/gen/g039.go2 @@ -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)