From 06a43e4ab62bc5f8353e1c6ed5267d51ce2b483c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 25 Feb 2022 14:56:04 -0800 Subject: [PATCH] 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 Run-TryBot: Dan Scales TryBot-Result: Gopher Robot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 13 ++++++++----- src/cmd/compile/internal/typecheck/subr.go | 6 +++--- test/typeparam/issue51367.dir/a.go | 14 ++++++++++++++ test/typeparam/issue51367.dir/main.go | 13 +++++++++++++ test/typeparam/issue51367.go | 7 +++++++ 5 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 test/typeparam/issue51367.dir/a.go create mode 100644 test/typeparam/issue51367.dir/main.go create mode 100644 test/typeparam/issue51367.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 807794dc30..9d17d5ffd1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -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 { diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 9892471142..181066ba96 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -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 diff --git a/test/typeparam/issue51367.dir/a.go b/test/typeparam/issue51367.dir/a.go new file mode 100644 index 0000000000..be0c3b0688 --- /dev/null +++ b/test/typeparam/issue51367.dir/a.go @@ -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() +} diff --git a/test/typeparam/issue51367.dir/main.go b/test/typeparam/issue51367.dir/main.go new file mode 100644 index 0000000000..64273d313b --- /dev/null +++ b/test/typeparam/issue51367.dir/main.go @@ -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]() +} diff --git a/test/typeparam/issue51367.go b/test/typeparam/issue51367.go new file mode 100644 index 0000000000..642f4bf49f --- /dev/null +++ b/test/typeparam/issue51367.go @@ -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