From 4a97fe8c2298ae879904d3cf304ca29500abf169 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 20 Jul 2021 14:52:19 -0700 Subject: [PATCH] [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 Trust: Dan Scales Trust: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 63 +++++++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 9e0f198262..460d926a0d 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -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 + } +}