From 5cb84f0604797df436d8fde548d4f797b3a6c245 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 21 Jul 2021 19:17:20 -0700 Subject: [PATCH] [dev.typeparams] cmd/compile: make sure types added to the dictionary are instantiated correctly 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 Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 31 ++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 71edc82dea..59f11bbe23 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -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() {