diff options
author | Robert Griesemer <gri@golang.org> | 2023-08-14 14:07:56 -0700 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2023-08-17 21:05:01 +0000 |
commit | 7437db10858fa147da00a2b67444ed42200bf161 (patch) | |
tree | 2921cf4abb6c3ee057957a2dd6defd40142a3e4b | |
parent | ed527ecfb2042fb60e1ee45ecef77e904d5ba8b3 (diff) | |
download | go-7437db10858fa147da00a2b67444ed42200bf161.tar.gz go-7437db10858fa147da00a2b67444ed42200bf161.zip |
[release-branch.go1.21] go/types, types2: use exact unification when comparing interface methods
Irrespective of whether unification is exact or inexact, method
signatures of interfaces must always match exactly: a type never
satisfies/implements an interface if relevant method signatures
are different (i.e., not identical, possibly after substitution).
Fixes #61959.
Change-Id: I20c0aa28ac86e2edec615b40f2269938e4a96938
Reviewed-on: https://go-review.googlesource.com/c/go/+/519435
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/519416
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
-rw-r--r-- | src/cmd/compile/internal/types2/unify.go | 6 | ||||
-rw-r--r-- | src/go/types/unify.go | 6 | ||||
-rw-r--r-- | src/internal/types/testdata/fixedbugs/issue61879.go | 57 |
3 files changed, 63 insertions, 6 deletions
diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 94830e94f7..eddd808cb7 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -505,7 +505,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { } // All xmethods must exist in ymethods and corresponding signatures must unify. for _, xm := range xmethods { - if ym := ymap[xm.Id()]; ym == nil || !u.nify(xm.typ, ym.typ, emode, p) { + if ym := ymap[xm.Id()]; ym == nil || !u.nify(xm.typ, ym.typ, exact, p) { return false } } @@ -526,7 +526,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { xmethods := xi.typeSet().methods for _, xm := range xmethods { obj, _, _ := LookupFieldOrMethod(y, false, xm.pkg, xm.name) - if ym, _ := obj.(*Func); ym == nil || !u.nify(xm.typ, ym.typ, emode, p) { + if ym, _ := obj.(*Func); ym == nil || !u.nify(xm.typ, ym.typ, exact, p) { return false } } @@ -685,7 +685,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { } for i, f := range a { g := b[i] - if f.Id() != g.Id() || !u.nify(f.typ, g.typ, emode, q) { + if f.Id() != g.Id() || !u.nify(f.typ, g.typ, exact, q) { return false } } diff --git a/src/go/types/unify.go b/src/go/types/unify.go index bef851f423..56b258ae35 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -507,7 +507,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { } // All xmethods must exist in ymethods and corresponding signatures must unify. for _, xm := range xmethods { - if ym := ymap[xm.Id()]; ym == nil || !u.nify(xm.typ, ym.typ, emode, p) { + if ym := ymap[xm.Id()]; ym == nil || !u.nify(xm.typ, ym.typ, exact, p) { return false } } @@ -528,7 +528,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { xmethods := xi.typeSet().methods for _, xm := range xmethods { obj, _, _ := LookupFieldOrMethod(y, false, xm.pkg, xm.name) - if ym, _ := obj.(*Func); ym == nil || !u.nify(xm.typ, ym.typ, emode, p) { + if ym, _ := obj.(*Func); ym == nil || !u.nify(xm.typ, ym.typ, exact, p) { return false } } @@ -687,7 +687,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { } for i, f := range a { g := b[i] - if f.Id() != g.Id() || !u.nify(f.typ, g.typ, emode, q) { + if f.Id() != g.Id() || !u.nify(f.typ, g.typ, exact, q) { return false } } diff --git a/src/internal/types/testdata/fixedbugs/issue61879.go b/src/internal/types/testdata/fixedbugs/issue61879.go new file mode 100644 index 0000000000..542bc2d68a --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue61879.go @@ -0,0 +1,57 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "fmt" + +type Interface[T any] interface { + m(Interface[T]) +} + +func f[S []Interface[T], T any](S) {} + +func _() { + var s []Interface[int] + f(s) // panic here +} + +// Larger example from issue + +type InterfaceA[T comparable] interface { + setData(string) InterfaceA[T] +} + +type ImplA[T comparable] struct { + data string + args []any +} + +func NewInterfaceA[T comparable](args ...any) InterfaceA[T] { + return &ImplA[T]{ + data: fmt.Sprintf("%v", args...), + args: args, + } +} + +func (k *ImplA[T]) setData(data string) InterfaceA[T] { + k.data = data + return k +} + +func Foo[M ~map[InterfaceA[T]]V, T comparable, V any](m M) { + // DO SOMETHING HERE + return +} + +func Bar() { + keys := make([]InterfaceA[int], 0, 10) + m := make(map[InterfaceA[int]]int) + for i := 0; i < 10; i++ { + keys = append(keys, NewInterfaceA[int](i)) + m[keys[i]] = i + } + + Foo(m) // panic here +} |