Skip to content

Commit 6578030

Browse files
[dev.go2go] go/go2go: handle fields promoted through embedded type parameter
Fixes #39678 Change-Id: Ib74d15795ab85ad0b1e58096302a9a88810242c5 Reviewed-on: https://go-review.googlesource.com/c/go/+/238857 Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 20dbf4d commit 6578030

File tree

2 files changed

+80
-25
lines changed

2 files changed

+80
-25
lines changed

src/go/go2go/rewrite.go

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -584,31 +584,7 @@ func (t *translator) translateExpr(pe *ast.Expr) {
584584
case *ast.ParenExpr:
585585
t.translateExpr(&e.X)
586586
case *ast.SelectorExpr:
587-
t.translateExpr(&e.X)
588-
589-
// Handle references to instantiated embedded fields.
590-
// We have to rewrite the name to the name used in
591-
// the translated struct definition.
592-
obj := t.importer.info.ObjectOf(e.Sel)
593-
if obj == nil {
594-
break
595-
}
596-
f, ok := obj.(*types.Var)
597-
if !ok || !f.Embedded() {
598-
break
599-
}
600-
named, ok := f.Type().(*types.Named)
601-
if !ok || len(named.TArgs()) == 0 {
602-
break
603-
}
604-
if obj.Name() != named.Obj().Name() {
605-
break
606-
}
607-
_, id := t.lookupInstantiatedType(named)
608-
*pe = &ast.SelectorExpr{
609-
X: e.X,
610-
Sel: id,
611-
}
587+
t.translateSelectorExpr(pe)
612588
case *ast.IndexExpr:
613589
t.translateExpr(&e.X)
614590
t.translateExpr(&e.Index)
@@ -661,6 +637,63 @@ func (t *translator) translateExpr(pe *ast.Expr) {
661637
}
662638
}
663639

640+
// translateSelectorExpr translates a selector expression
641+
// from Go with contracts to Go 1.
642+
func (t *translator) translateSelectorExpr(pe *ast.Expr) {
643+
e := (*pe).(*ast.SelectorExpr)
644+
645+
t.translateExpr(&e.X)
646+
647+
obj := t.importer.info.ObjectOf(e.Sel)
648+
if obj == nil {
649+
return
650+
}
651+
652+
// Handle references to promoted fields and methods,
653+
// if they go through an embedded instantiated field.
654+
// We have to add a reference to the field we inserted.
655+
if xType := t.lookupType(e.X); xType != nil {
656+
if ptr := xType.Pointer(); ptr != nil {
657+
xType = ptr.Elem()
658+
}
659+
fobj, indexes, _ := types.LookupFieldOrMethod(xType, true, obj.Pkg(), obj.Name())
660+
if fobj != nil && len(indexes) > 1 {
661+
for _, index := range indexes[:len(indexes)-1] {
662+
xf := xType.Struct().Field(index)
663+
if xf.Name() == types.TypeString(xf.Type(), types.RelativeTo(xf.Pkg())) {
664+
continue
665+
}
666+
e.X = &ast.SelectorExpr{
667+
X: e.X,
668+
Sel: ast.NewIdent(xf.Name()),
669+
}
670+
xType = xf.Type()
671+
if ptr := xType.Pointer(); ptr != nil {
672+
xType = ptr.Elem()
673+
}
674+
}
675+
}
676+
}
677+
678+
// Handle references to instantiated embedded fields.
679+
// We have to rewrite the name to the name used in
680+
// the translated struct definition.
681+
if f, ok := obj.(*types.Var); ok && f.Embedded() {
682+
named, ok := f.Type().(*types.Named)
683+
if !ok || len(named.TArgs()) == 0 {
684+
return
685+
}
686+
if obj.Name() != named.Obj().Name() {
687+
return
688+
}
689+
_, id := t.lookupInstantiatedType(named)
690+
*pe = &ast.SelectorExpr{
691+
X: e.X,
692+
Sel: id,
693+
}
694+
}
695+
}
696+
664697
// TODO(iant) refactor code and get rid of this?
665698
func splitFieldList(fl *ast.FieldList) (methods *ast.FieldList, types []ast.Expr) {
666699
if fl == nil {

test/gen/g027.go2

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// compile
2+
3+
// Copyright 2020 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Issue 39678.
8+
package p
9+
10+
type B(type T) struct {
11+
T
12+
}
13+
14+
type C struct {
15+
F int
16+
}
17+
18+
type BC B(C)
19+
20+
func F(s BC) {
21+
s.F = 7
22+
}

0 commit comments

Comments
 (0)