Commit e5f01aee authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/gc: do not nop-convert equivalent but different interface types.

The cached computed interface tables are indexed by the interface
types, not by the unnamed underlying interfaces

To preserve the invariants expected by interface comparison, an
itab generated for an interface type must not be used for a value
of a different interface type even if the representation is identical.

Fixes #7207.

LGTM=rsc
R=rsc, iant, khr
CC=golang-codereviews
https://golang.org/cl/69210044
parent b7b844d4
...@@ -1223,8 +1223,10 @@ assignop(Type *src, Type *dst, char **why) ...@@ -1223,8 +1223,10 @@ assignop(Type *src, Type *dst, char **why)
// 2. src and dst have identical underlying types // 2. src and dst have identical underlying types
// and either src or dst is not a named type or // and either src or dst is not a named type or
// both are interface types. // both are empty interface types.
if(eqtype(src->orig, dst->orig) && (src->sym == S || dst->sym == S || src->etype == TINTER)) // For assignable but different non-empty interface types,
// we want to recompute the itab.
if(eqtype(src->orig, dst->orig) && (src->sym == S || dst->sym == S || isnilinter(src)))
return OCONVNOP; return OCONVNOP;
// 3. dst is an interface type and src implements dst. // 3. dst is an interface type and src implements dst.
......
...@@ -35,6 +35,10 @@ func istrue(b bool) { ...@@ -35,6 +35,10 @@ func istrue(b bool) {
type T *int type T *int
type X int
func (X) x() {}
func main() { func main() {
var a []int var a []int
var b map[string]int var b map[string]int
...@@ -129,6 +133,44 @@ func main() { ...@@ -129,6 +133,44 @@ func main() {
panic("bad m[c]") panic("bad m[c]")
} }
// interface comparisons (issue 7207)
{
type I1 interface {
x()
}
type I2 interface {
x()
}
a1 := I1(X(0))
b1 := I1(X(1))
a2 := I2(X(0))
b2 := I2(X(1))
a3 := I1(a2)
a4 := I2(a1)
var e interface{} = X(0)
a5 := e.(I1)
a6 := e.(I2)
isfalse(a1 == b1)
isfalse(a1 == b2)
isfalse(a2 == b1)
isfalse(a2 == b2)
istrue(a1 == a2)
istrue(a1 == a3)
istrue(a1 == a4)
istrue(a1 == a5)
istrue(a1 == a6)
istrue(a2 == a3)
istrue(a2 == a4)
istrue(a2 == a5)
istrue(a2 == a6)
istrue(a3 == a4)
istrue(a3 == a5)
istrue(a3 == a6)
istrue(a4 == a5)
istrue(a4 == a6)
istrue(a5 == a6)
}
// non-interface comparisons // non-interface comparisons
{ {
c := make(chan int) c := make(chan int)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment