cmd/compile: fix case for structural types where we should be looking at typeparams

In getInstantiation, we were not computing tparams correctly for the
case where the receiver of a method was a fully-instantiated type. This
wasn't affecting later parts of the function, since method
instantiations of fully-instantiated types were already being calculated
in an earlier path. But it did give us a non-typeparam when trying to
see if a shape was associated with a type param with a structural type.
The fix is just to get the typeparams associated with the base generic
type. Then we can eliminate a conditional check later in the code.
The tparam parameter of Shapify should always be non-nil

Fixes #51367

Change-Id: I6f95fe603886148b2dad0c581416c51373c85009
Reviewed-on: https://go-review.googlesource.com/c/go/+/388116
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Dan Scales 2022-02-25 14:56:04 -08:00
parent 0907d57abf
commit 06a43e4ab6
5 changed files with 45 additions and 8 deletions

View file

@ -641,6 +641,11 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
// over any pointer)
recvType := nameNode.Type().Recv().Type
recvType = deref(recvType)
if recvType.IsFullyInstantiated() {
// Get the type of the base generic type, so we get
// its original typeparams.
recvType = recvType.OrigSym().Def.(*ir.Name).Type()
}
tparams = recvType.RParams()
} else {
fields := nameNode.Type().TParams().Fields().Slice()
@ -657,11 +662,9 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
s1 := make([]*types.Type, len(shapes))
for i, t := range shapes {
var tparam *types.Type
if tparams[i].Kind() == types.TTYPEPARAM {
// Shapes are grouped differently for structural types, so we
// pass the type param to Shapify(), so we can distinguish.
tparam = tparams[i]
}
// Shapes are grouped differently for structural types, so we
// pass the type param to Shapify(), so we can distinguish.
tparam = tparams[i]
if !t.IsShape() {
s1[i] = typecheck.Shapify(t, i, tparam)
} else {

View file

@ -1432,9 +1432,9 @@ func genericTypeName(sym *types.Sym) string {
// For now, we only consider two types to have the same shape, if they have exactly
// the same underlying type or they are both pointer types.
//
// tparam is the associated typeparam. If there is a structural type for
// the associated type param (not common), then a pointer type t is mapped to its
// underlying type, rather than being merged with other pointers.
// tparam is the associated typeparam - it must be TTYPEPARAM type. If there is a
// structural type for the associated type param (not common), then a pointer type t
// is mapped to its underlying type, rather than being merged with other pointers.
//
// Shape types are also distinguished by the index of the type in a type param/arg
// list. We need to do this so we can distinguish and substitute properly for two

View file

@ -0,0 +1,14 @@
// Copyright 2022 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 a
type A[T any] struct{}
func (_ A[T]) Method() {}
func DoSomething[P any]() {
a := A[*byte]{}
a.Method()
}

View file

@ -0,0 +1,13 @@
// Copyright 2022 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 (
"a"
)
func main() {
a.DoSomething[byte]()
}

View file

@ -0,0 +1,7 @@
// rundir -G=3
// Copyright 2022 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 ignored