]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: make sure types added to the dictionary are instantiate...
authorKeith Randall <khr@golang.org>
Thu, 22 Jul 2021 02:17:20 +0000 (19:17 -0700)
committerKeith Randall <khr@golang.org>
Thu, 22 Jul 2021 18:09:49 +0000 (18:09 +0000)
Make sure the instantiating types are the type parameters of the containing
function (or types derived from those).

The one exception is the argument of a OFUNCINST, whose type
parameters are those of the declaration site of the function or method
being instantiated. We skip those types.

Change-Id: I4b3ff22eb8a81a76476930cf8ed2a7dd6489d8b8
Reviewed-on: https://go-review.googlesource.com/c/go/+/336352
Trust: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
src/cmd/compile/internal/noder/stencil.go

index 71edc82deab8a23e14e0b749f12e6bd869388af9..59f11bbe23704a630cecf296f924b7327a6bee28 100644 (file)
@@ -22,6 +22,9 @@ import (
        "strconv"
 )
 
+// Enable extra consistency checks.
+const doubleCheck = true
+
 func assert(p bool) {
        base.Assert(p)
 }
@@ -1820,7 +1823,6 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo {
                                ir.Visit(n1, visitFunc)
                        }
                }
-
                addType(&info, n, n.Type())
        }
 
@@ -1847,9 +1849,17 @@ func addType(info *gfInfo, n ir.Node, t *types.Type) {
        if t.IsTypeParam() && t.Underlying() == t {
                return
        }
-       if !parameterizedBy(t, info.tparams) {
+       if t.Kind() == types.TFUNC && n != nil &&
+               (t.Recv() != nil ||
+                       n.Op() == ir.ONAME && n.Name().Class == ir.PFUNC) {
+               // Don't use the type of a named generic function or method,
+               // since that is parameterized by other typeparams.
+               // (They all come from arguments of a FUNCINST node.)
                return
        }
+       if doubleCheck && !parameterizedBy(t, info.tparams) {
+               base.Fatalf("adding type with invalid parameters %+v", t)
+       }
        if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() {
                // Multiple return values are not a relevant new type (?).
                return
@@ -1872,13 +1882,25 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty
                return true
        }
        visited[t] = true
+
+       if t.Sym() != nil && len(t.RParams()) > 0 {
+               // This defined type is instantiated. Check the instantiating types.
+               for _, r := range t.RParams() {
+                       if !parameterizedBy1(r, params, visited) {
+                               return false
+                       }
+               }
+               return true
+       }
        switch t.Kind() {
        case types.TTYPEPARAM:
+               // Check if t is one of the allowed parameters in scope.
                for _, p := range params {
                        if p == t {
                                return true
                        }
                }
+               // Couldn't find t in the list of allowed parameters.
                return false
 
        case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN:
@@ -1888,10 +1910,7 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty
                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)
+               return parameterizedBy1(t.TParams(), params, visited) && parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited)
 
        case types.TSTRUCT:
                for _, f := range t.Fields().Slice() {