diff options
author | Robert Findley <rfindley@google.com> | 2021-11-22 12:47:53 -0500 |
---|---|---|
committer | Robert Findley <rfindley@google.com> | 2021-11-22 20:32:29 +0000 |
commit | 773f43b35638092f9c0dc56f4a468dce2eb3a8ef (patch) | |
tree | 7245582234f832258a7222ec8923da8d6a9c062b /src/cmd/compile/internal/types2/predicates.go | |
parent | 189b4a2f428be7264db76e5275c96d98b847383b (diff) | |
download | go-773f43b35638092f9c0dc56f4a468dce2eb3a8ef.tar.gz go-773f43b35638092f9c0dc56f4a468dce2eb3a8ef.zip |
go/types, types2: substitute for type parameters in signatures when
comparing type identity
Generic signatures should be considered identical modulo type parameter
renaming. Update Identical to reflect this, by substituting type
parameters.
Fixes #49722
Change-Id: I33743768c72d8aa59c29bf72fcbabc5974f0b805
Reviewed-on: https://go-review.googlesource.com/c/go/+/366178
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/types2/predicates.go')
-rw-r--r-- | src/cmd/compile/internal/types2/predicates.go | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index e7834a0f9e..cf2993f68b 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -235,19 +235,56 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { } case *Signature: - // Two function types are identical if they have the same number of parameters - // and result values, corresponding parameter and result types are identical, - // and either both functions are variadic or neither is. Parameter and result - // names are not required to match. - // Generic functions must also have matching type parameter lists, but for the - // parameter names. - if y, ok := y.(*Signature); ok { - return x.variadic == y.variadic && - identicalTParams(x.TypeParams().list(), y.TypeParams().list(), cmpTags, p) && - identical(x.params, y.params, cmpTags, p) && - identical(x.results, y.results, cmpTags, p) + y, _ := y.(*Signature) + if y == nil { + return false + } + + // Two function types are identical if they have the same number of + // parameters and result values, corresponding parameter and result types + // are identical, and either both functions are variadic or neither is. + // Parameter and result names are not required to match, and type + // parameters are considered identical modulo renaming. + + if x.TypeParams().Len() != y.TypeParams().Len() { + return false + } + + // In the case of generic signatures, we will substitute in yparams and + // yresults. + yparams := y.params + yresults := y.results + + if x.TypeParams().Len() > 0 { + // We must ignore type parameter names when comparing x and y. The + // easiest way to do this is to substitute x's type parameters for y's. + xtparams := x.TypeParams().list() + ytparams := y.TypeParams().list() + + var targs []Type + for i := range xtparams { + targs = append(targs, x.TypeParams().At(i)) + } + smap := makeSubstMap(ytparams, targs) + + var check *Checker // ok to call subst on a nil *Checker + + // Constraints must be pair-wise identical, after substitution. + for i, xtparam := range xtparams { + ybound := check.subst(nopos, ytparams[i].bound, smap, nil) + if !identical(xtparam.bound, ybound, cmpTags, p) { + return false + } + } + + yparams = check.subst(nopos, y.params, smap, nil).(*Tuple) + yresults = check.subst(nopos, y.results, smap, nil).(*Tuple) } + return x.variadic == y.variadic && + identical(x.params, yparams, cmpTags, p) && + identical(x.results, yresults, cmpTags, p) + case *Union: if y, _ := y.(*Union); y != nil { xset := computeUnionTypeSet(nil, nopos, x) @@ -389,19 +426,6 @@ func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool return Identical(xorig, yorig) } -func identicalTParams(x, y []*TypeParam, cmpTags bool, p *ifacePair) bool { - if len(x) != len(y) { - return false - } - for i, x := range x { - y := y[i] - if !identical(x.bound, y.bound, cmpTags, p) { - return false - } - } - return true -} - // Default returns the default "typed" type for an "untyped" type; // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. |