]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: avoid adding incorrectly instantiated types to the...
authorKeith Randall <khr@golang.org>
Tue, 20 Jul 2021 21:52:19 +0000 (14:52 -0700)
committerKeith Randall <khr@golang.org>
Wed, 21 Jul 2021 21:05:50 +0000 (21:05 +0000)
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>

src/cmd/compile/internal/noder/stencil.go

index 9e0f19826220a45f2e36cd9defdf1cbfb9176c68..460d926a0d64ec6ed500e99319c1a8c18b2400c6 100644 (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
+       }
+}