Skip to content
This repository has been archived by the owner on May 2, 2018. It is now read-only.

Commit

Permalink
cmd/gc: do not nop-convert equivalent but different interface types.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
remyoudompheng committed Feb 27, 2014
1 parent b7b844d commit e5f01ae
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/cmd/gc/subr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1223,8 +1223,10 @@ assignop(Type *src, Type *dst, char **why)

// 2. src and dst have identical underlying types
// and either src or dst is not a named type or
// both are interface types.
if(eqtype(src->orig, dst->orig) && (src->sym == S || dst->sym == S || src->etype == TINTER))
// both are empty interface types.
// 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;

// 3. dst is an interface type and src implements dst.
Expand Down
42 changes: 42 additions & 0 deletions test/cmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func istrue(b bool) {

type T *int

type X int

func (X) x() {}

func main() {
var a []int
var b map[string]int
Expand Down Expand Up @@ -129,6 +133,44 @@ func main() {
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
{
c := make(chan int)
Expand Down

0 comments on commit e5f01ae

Please sign in to comment.