[dev.typeparams] cmd/compile: avoid adding incorrectly instantiated types to the dictionary

FUNCINST nodes aren't instantiated correctly. Skip those types when
adding to the set of types considered for the dictionary.  Those types
include those which are uninstantiated(have tparams), and those with
type parameters that aren't a parameter of the containing function
(they are the type parameter of the function being called).

Allow func types to be put in the dictionary.

Change-Id: I26bab85d3eebc2f54d02b4bba5e31407faf7c5b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/336129
Reviewed-by: Dan Scales <danscales@google.com>
Trust: Dan Scales <danscales@google.com>
Trust: Keith Randall <khr@golang.org>
This commit is contained in:
Keith Randall 2021-07-20 14:52:19 -07:00
parent 2fe4b14795
commit 4a97fe8c22

View file

@ -1836,11 +1836,7 @@ func addType(info *gfInfo, n ir.Node, t *types.Type) {
if t.IsTypeParam() && t.Underlying() == t {
return
}
if t.Kind() == types.TFUNC && n != nil &&
(n.Op() != ir.ONAME || n.Name().Class == ir.PFUNC) {
// For now, only record function types that are associate with a
// local/global variable (a name which is not a named global
// function).
if !parameterizedBy(t, info.tparams) {
return
}
if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() {
@ -1855,3 +1851,60 @@ func addType(info *gfInfo, n ir.Node, t *types.Type) {
}
info.derivedTypes = append(info.derivedTypes, t)
}
// parameterizedBy returns true if t is parameterized by (at most) params.
func parameterizedBy(t *types.Type, params []*types.Type) bool {
return parameterizedBy1(t, params, map[*types.Type]bool{})
}
func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Type]bool) bool {
if visited[t] {
return true
}
visited[t] = true
switch t.Kind() {
case types.TTYPEPARAM:
for _, p := range params {
if p == t {
return true
}
}
return false
case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN:
return parameterizedBy1(t.Elem(), params, visited)
case types.TMAP:
return parameterizedBy1(t.Key(), params, visited) && parameterizedBy1(t.Elem(), params, visited)
case types.TFUNC:
if t.NumTParams() > 0 {
return false
}
return parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited)
case types.TSTRUCT:
for _, f := range t.Fields().Slice() {
if !parameterizedBy1(f.Type, params, visited) {
return false
}
}
return true
case types.TINTER:
for _, f := range t.Methods().Slice() {
if !parameterizedBy1(f.Type, params, visited) {
return false
}
}
return true
case types.TINT, types.TINT8, types.TINT16, types.TINT32, types.TINT64,
types.TUINT, types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64,
types.TUINTPTR, types.TBOOL, types.TSTRING, types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
return true
default:
base.Fatalf("bad type kind %+v", t)
return true
}
}