cmd/compile: fix wrong instantiated type for embedded receiver

In case of embedded field, if the receiver was fully instantiated, we
must use its instantiated type, instead of passing the type params of
the base receiver.

Fixes #47797
Fixes #48253

Change-Id: I97613e7e669a72605137e82406f7bf5fbb629378
Reviewed-on: https://go-review.googlesource.com/c/go/+/348549
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
Cuong Manh Le 2021-09-09 01:11:26 +07:00
parent d62866ef79
commit 2481f6e367
3 changed files with 59 additions and 15 deletions

View file

@ -360,12 +360,10 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
n.(*ir.SelectorExpr).Selection.Nname = method
typed(method.Type(), n)
// selinfo.Targs() are the types used to
// instantiate the type of receiver
targs2 := getTargs(selinfo)
targs := make([]ir.Node, targs2.Len())
xt := deref(x.Type())
targs := make([]ir.Node, len(xt.RParams()))
for i := range targs {
targs[i] = ir.TypeNode(g.typ(targs2.At(i)))
targs[i] = ir.TypeNode(xt.RParams()[i])
}
// Create function instantiation with the type
@ -388,16 +386,6 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
return n
}
// getTargs gets the targs associated with the receiver of a selected method
func getTargs(selinfo *types2.Selection) *types2.TypeList {
r := deref2(selinfo.Recv())
n := types2.AsNamed(r)
if n == nil {
base.Fatalf("Incorrect type for selinfo %v", selinfo)
}
return n.TypeArgs()
}
func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
return g.exprs(unpackListExpr(expr))
}

View file

@ -0,0 +1,22 @@
// compile -G=3
// Copyright 2021 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 Foo[T any] struct {
Val T
}
func (f Foo[T]) Bat() {}
type Bar struct {
Foo[int]
}
func foo() {
var b Bar
b.Bat()
}

View file

@ -0,0 +1,34 @@
// run -gcflags="-G=3"
// Copyright 2021 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 main
import (
"reflect"
)
type A[T any] struct {
B[int]
}
type B[T any] struct {
}
func (b B[T]) Bat() {
t := new(T)
if tt := reflect.TypeOf(t); tt.Kind() != reflect.Pointer || tt.Elem().Kind() != reflect.Int {
panic("unexpected type, want: *int, got: "+tt.String())
}
}
type Foo struct {
A[string]
}
func main() {
Foo{}.A.Bat()
Foo{}.A.B.Bat()
Foo{}.Bat()
}