]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: do not nop-convert equivalent but different interface types.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Thu, 27 Feb 2014 07:07:50 +0000 (08:07 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Thu, 27 Feb 2014 07:07:50 +0000 (08:07 +0100)
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

src/cmd/gc/subr.c
test/cmp.go

index a32590e003dca0cb95386e032ae18b55bc63d39c..01a5c435aabcb9fced0965d9f1128847f5fa8456 100644 (file)
@@ -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.
index 9ac0ebe79d3dc00d217f1bec75adc71f7889445a..80d1bf699fd9805cd0fb7f52a562e88f5efdc5cc 100644 (file)
@@ -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
@@ -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)