From e5f01aee04dc6313c85dab78305adf499e1f7bfa Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9my=20Oudompheng?= Date: Thu, 27 Feb 2014 08:07:50 +0100 Subject: [PATCH] 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 --- src/cmd/gc/subr.c | 6 ++++-- test/cmp.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index a32590e003..01a5c435aa 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -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. diff --git a/test/cmp.go b/test/cmp.go index 9ac0ebe79d..80d1bf699f 100644 --- a/test/cmp.go +++ b/test/cmp.go @@ -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) -- 2.48.1