1
0
mirror of https://github.com/golang/go synced 2024-11-22 23:50:03 -07:00

[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 <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>
This commit is contained in:
Keith Randall 2021-07-21 19:17:20 -07:00
parent 73162a54c2
commit 5cb84f0604

View File

@ -22,6 +22,9 @@ import (
"strconv" "strconv"
) )
// Enable extra consistency checks.
const doubleCheck = true
func assert(p bool) { func assert(p bool) {
base.Assert(p) base.Assert(p)
} }
@ -1820,7 +1823,6 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo {
ir.Visit(n1, visitFunc) ir.Visit(n1, visitFunc)
} }
} }
addType(&info, n, n.Type()) 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 { if t.IsTypeParam() && t.Underlying() == t {
return 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 return
} }
if doubleCheck && !parameterizedBy(t, info.tparams) {
base.Fatalf("adding type with invalid parameters %+v", t)
}
if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() { if t.Kind() == types.TSTRUCT && t.IsFuncArgStruct() {
// Multiple return values are not a relevant new type (?). // Multiple return values are not a relevant new type (?).
return return
@ -1872,13 +1882,25 @@ func parameterizedBy1(t *types.Type, params []*types.Type, visited map[*types.Ty
return true return true
} }
visited[t] = 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() { switch t.Kind() {
case types.TTYPEPARAM: case types.TTYPEPARAM:
// Check if t is one of the allowed parameters in scope.
for _, p := range params { for _, p := range params {
if p == t { if p == t {
return true return true
} }
} }
// Couldn't find t in the list of allowed parameters.
return false return false
case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN: 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) return parameterizedBy1(t.Key(), params, visited) && parameterizedBy1(t.Elem(), params, visited)
case types.TFUNC: case types.TFUNC:
if t.NumTParams() > 0 { return parameterizedBy1(t.TParams(), params, visited) && parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited)
return false
}
return parameterizedBy1(t.Recvs(), params, visited) && parameterizedBy1(t.Params(), params, visited) && parameterizedBy1(t.Results(), params, visited)
case types.TSTRUCT: case types.TSTRUCT:
for _, f := range t.Fields().Slice() { for _, f := range t.Fields().Slice() {