mirror of
https://github.com/golang/go
synced 2024-11-14 06:30:22 -07:00
e5f01aee04
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
489 lines
7.6 KiB
Go
489 lines
7.6 KiB
Go
// run
|
|
|
|
// Copyright 2009 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.
|
|
|
|
// Test equality and inequality operations.
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"unsafe"
|
|
)
|
|
|
|
var global bool
|
|
|
|
func use(b bool) { global = b }
|
|
|
|
func stringptr(s string) uintptr { return *(*uintptr)(unsafe.Pointer(&s)) }
|
|
|
|
func isfalse(b bool) {
|
|
if b {
|
|
// stack will explain where
|
|
panic("wanted false, got true")
|
|
}
|
|
}
|
|
|
|
func istrue(b bool) {
|
|
if !b {
|
|
// stack will explain where
|
|
panic("wanted true, got false")
|
|
}
|
|
}
|
|
|
|
type T *int
|
|
|
|
type X int
|
|
|
|
func (X) x() {}
|
|
|
|
func main() {
|
|
var a []int
|
|
var b map[string]int
|
|
|
|
var c string = "hello"
|
|
var d string = "hel" // try to get different pointer
|
|
d = d + "lo"
|
|
|
|
// go.tools/ssa/interp can't handle unsafe.Pointer.
|
|
if os.Getenv("GOSSAINTERP") == "" {
|
|
if stringptr(c) == stringptr(d) {
|
|
panic("compiler too smart -- got same string")
|
|
}
|
|
}
|
|
|
|
var e = make(chan int)
|
|
|
|
var ia interface{} = a
|
|
var ib interface{} = b
|
|
var ic interface{} = c
|
|
var id interface{} = d
|
|
var ie interface{} = e
|
|
|
|
// these comparisons are okay because
|
|
// string compare is okay and the others
|
|
// are comparisons where the types differ.
|
|
isfalse(ia == ib)
|
|
isfalse(ia == ic)
|
|
isfalse(ia == id)
|
|
isfalse(ib == ic)
|
|
isfalse(ib == id)
|
|
istrue(ic == id)
|
|
istrue(ie == ie)
|
|
|
|
istrue(ia != ib)
|
|
istrue(ia != ic)
|
|
istrue(ia != id)
|
|
istrue(ib != ic)
|
|
istrue(ib != id)
|
|
isfalse(ic != id)
|
|
isfalse(ie != ie)
|
|
|
|
// these are not okay, because there is no comparison on slices or maps.
|
|
//isfalse(a == ib)
|
|
//isfalse(a == ic)
|
|
//isfalse(a == id)
|
|
//isfalse(b == ic)
|
|
//isfalse(b == id)
|
|
|
|
istrue(c == id)
|
|
istrue(e == ie)
|
|
|
|
//isfalse(ia == b)
|
|
isfalse(ia == c)
|
|
isfalse(ia == d)
|
|
isfalse(ib == c)
|
|
isfalse(ib == d)
|
|
istrue(ic == d)
|
|
istrue(ie == e)
|
|
|
|
//istrue(a != ib)
|
|
//istrue(a != ic)
|
|
//istrue(a != id)
|
|
//istrue(b != ic)
|
|
//istrue(b != id)
|
|
isfalse(c != id)
|
|
isfalse(e != ie)
|
|
|
|
//istrue(ia != b)
|
|
istrue(ia != c)
|
|
istrue(ia != d)
|
|
istrue(ib != c)
|
|
istrue(ib != d)
|
|
isfalse(ic != d)
|
|
isfalse(ie != e)
|
|
|
|
// 6g used to let this go through as true.
|
|
var g uint64 = 123
|
|
var h int64 = 123
|
|
var ig interface{} = g
|
|
var ih interface{} = h
|
|
isfalse(ig == ih)
|
|
istrue(ig != ih)
|
|
|
|
// map of interface should use == on interface values,
|
|
// not memory.
|
|
var m = make(map[interface{}]int)
|
|
m[ic] = 1
|
|
m[id] = 2
|
|
if m[c] != 2 {
|
|
println("m[c] = ", 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
|
|
{
|
|
c := make(chan int)
|
|
c1 := (<-chan int)(c)
|
|
c2 := (chan<- int)(c)
|
|
istrue(c == c1)
|
|
istrue(c == c2)
|
|
istrue(c1 == c)
|
|
istrue(c2 == c)
|
|
|
|
isfalse(c != c1)
|
|
isfalse(c != c2)
|
|
isfalse(c1 != c)
|
|
isfalse(c2 != c)
|
|
|
|
d := make(chan int)
|
|
isfalse(c == d)
|
|
isfalse(d == c)
|
|
isfalse(d == c1)
|
|
isfalse(d == c2)
|
|
isfalse(c1 == d)
|
|
isfalse(c2 == d)
|
|
|
|
istrue(c != d)
|
|
istrue(d != c)
|
|
istrue(d != c1)
|
|
istrue(d != c2)
|
|
istrue(c1 != d)
|
|
istrue(c2 != d)
|
|
}
|
|
|
|
// named types vs not
|
|
{
|
|
var x = new(int)
|
|
var y T
|
|
var z T = x
|
|
|
|
isfalse(x == y)
|
|
istrue(x == z)
|
|
isfalse(y == z)
|
|
|
|
isfalse(y == x)
|
|
istrue(z == x)
|
|
isfalse(z == y)
|
|
|
|
istrue(x != y)
|
|
isfalse(x != z)
|
|
istrue(y != z)
|
|
|
|
istrue(y != x)
|
|
isfalse(z != x)
|
|
istrue(z != y)
|
|
}
|
|
|
|
// structs
|
|
{
|
|
var x = struct {
|
|
x int
|
|
y string
|
|
}{1, "hi"}
|
|
var y = struct {
|
|
x int
|
|
y string
|
|
}{2, "bye"}
|
|
var z = struct {
|
|
x int
|
|
y string
|
|
}{1, "hi"}
|
|
|
|
isfalse(x == y)
|
|
isfalse(y == x)
|
|
isfalse(y == z)
|
|
isfalse(z == y)
|
|
istrue(x == z)
|
|
istrue(z == x)
|
|
|
|
istrue(x != y)
|
|
istrue(y != x)
|
|
istrue(y != z)
|
|
istrue(z != y)
|
|
isfalse(x != z)
|
|
isfalse(z != x)
|
|
|
|
var m = make(map[struct {
|
|
x int
|
|
y string
|
|
}]int)
|
|
m[x] = 10
|
|
m[y] = 20
|
|
m[z] = 30
|
|
istrue(m[x] == 30)
|
|
istrue(m[y] == 20)
|
|
istrue(m[z] == 30)
|
|
istrue(m[x] != 10)
|
|
isfalse(m[x] != 30)
|
|
isfalse(m[y] != 20)
|
|
isfalse(m[z] != 30)
|
|
isfalse(m[x] == 10)
|
|
|
|
var m1 = make(map[struct {
|
|
x int
|
|
y string
|
|
}]struct {
|
|
x int
|
|
y string
|
|
})
|
|
m1[x] = x
|
|
m1[y] = y
|
|
m1[z] = z
|
|
istrue(m1[x] == z)
|
|
istrue(m1[y] == y)
|
|
istrue(m1[z] == z)
|
|
istrue(m1[x] == x)
|
|
isfalse(m1[x] != z)
|
|
isfalse(m1[y] != y)
|
|
isfalse(m1[z] != z)
|
|
isfalse(m1[x] != x)
|
|
|
|
var ix, iy, iz interface{} = x, y, z
|
|
|
|
isfalse(ix == iy)
|
|
isfalse(iy == ix)
|
|
isfalse(iy == iz)
|
|
isfalse(iz == iy)
|
|
istrue(ix == iz)
|
|
istrue(iz == ix)
|
|
|
|
isfalse(x == iy)
|
|
isfalse(y == ix)
|
|
isfalse(y == iz)
|
|
isfalse(z == iy)
|
|
istrue(x == iz)
|
|
istrue(z == ix)
|
|
|
|
isfalse(ix == y)
|
|
isfalse(iy == x)
|
|
isfalse(iy == z)
|
|
isfalse(iz == y)
|
|
istrue(ix == z)
|
|
istrue(iz == x)
|
|
|
|
istrue(ix != iy)
|
|
istrue(iy != ix)
|
|
istrue(iy != iz)
|
|
istrue(iz != iy)
|
|
isfalse(ix != iz)
|
|
isfalse(iz != ix)
|
|
|
|
istrue(x != iy)
|
|
istrue(y != ix)
|
|
istrue(y != iz)
|
|
istrue(z != iy)
|
|
isfalse(x != iz)
|
|
isfalse(z != ix)
|
|
|
|
istrue(ix != y)
|
|
istrue(iy != x)
|
|
istrue(iy != z)
|
|
istrue(iz != y)
|
|
isfalse(ix != z)
|
|
isfalse(iz != x)
|
|
}
|
|
|
|
// structs with _ fields
|
|
{
|
|
var x = struct {
|
|
x int
|
|
_ string
|
|
y float64
|
|
_ float64
|
|
z int
|
|
}{
|
|
x: 1, y: 2, z: 3,
|
|
}
|
|
var ix interface{} = x
|
|
|
|
istrue(x == x)
|
|
istrue(x == ix)
|
|
istrue(ix == x)
|
|
istrue(ix == ix)
|
|
}
|
|
|
|
// arrays
|
|
{
|
|
var x = [2]string{"1", "hi"}
|
|
var y = [2]string{"2", "bye"}
|
|
var z = [2]string{"1", "hi"}
|
|
|
|
isfalse(x == y)
|
|
isfalse(y == x)
|
|
isfalse(y == z)
|
|
isfalse(z == y)
|
|
istrue(x == z)
|
|
istrue(z == x)
|
|
|
|
istrue(x != y)
|
|
istrue(y != x)
|
|
istrue(y != z)
|
|
istrue(z != y)
|
|
isfalse(x != z)
|
|
isfalse(z != x)
|
|
|
|
var m = make(map[[2]string]int)
|
|
m[x] = 10
|
|
m[y] = 20
|
|
m[z] = 30
|
|
istrue(m[x] == 30)
|
|
istrue(m[y] == 20)
|
|
istrue(m[z] == 30)
|
|
isfalse(m[x] != 30)
|
|
isfalse(m[y] != 20)
|
|
isfalse(m[z] != 30)
|
|
|
|
var ix, iy, iz interface{} = x, y, z
|
|
|
|
isfalse(ix == iy)
|
|
isfalse(iy == ix)
|
|
isfalse(iy == iz)
|
|
isfalse(iz == iy)
|
|
istrue(ix == iz)
|
|
istrue(iz == ix)
|
|
|
|
isfalse(x == iy)
|
|
isfalse(y == ix)
|
|
isfalse(y == iz)
|
|
isfalse(z == iy)
|
|
istrue(x == iz)
|
|
istrue(z == ix)
|
|
|
|
isfalse(ix == y)
|
|
isfalse(iy == x)
|
|
isfalse(iy == z)
|
|
isfalse(iz == y)
|
|
istrue(ix == z)
|
|
istrue(iz == x)
|
|
|
|
istrue(ix != iy)
|
|
istrue(iy != ix)
|
|
istrue(iy != iz)
|
|
istrue(iz != iy)
|
|
isfalse(ix != iz)
|
|
isfalse(iz != ix)
|
|
|
|
istrue(x != iy)
|
|
istrue(y != ix)
|
|
istrue(y != iz)
|
|
istrue(z != iy)
|
|
isfalse(x != iz)
|
|
isfalse(z != ix)
|
|
|
|
istrue(ix != y)
|
|
istrue(iy != x)
|
|
istrue(iy != z)
|
|
istrue(iz != y)
|
|
isfalse(ix != z)
|
|
isfalse(iz != x)
|
|
}
|
|
|
|
// named booleans
|
|
{
|
|
type mybool bool
|
|
var b mybool
|
|
|
|
type T struct{ data [20]byte }
|
|
var x, y T
|
|
b = x == y
|
|
istrue(x == y)
|
|
istrue(bool(b))
|
|
|
|
m := make(map[string][10]interface{})
|
|
b = m["x"] == m["y"]
|
|
istrue(m["x"] == m["y"])
|
|
istrue(bool(b))
|
|
}
|
|
|
|
shouldPanic(p1)
|
|
shouldPanic(p2)
|
|
shouldPanic(p3)
|
|
shouldPanic(p4)
|
|
}
|
|
|
|
func p1() {
|
|
var a []int
|
|
var ia interface{} = a
|
|
use(ia == ia)
|
|
}
|
|
|
|
func p2() {
|
|
var b []int
|
|
var ib interface{} = b
|
|
use(ib == ib)
|
|
}
|
|
|
|
func p3() {
|
|
var a []int
|
|
var ia interface{} = a
|
|
var m = make(map[interface{}]int)
|
|
m[ia] = 1
|
|
}
|
|
|
|
func p4() {
|
|
var b []int
|
|
var ib interface{} = b
|
|
var m = make(map[interface{}]int)
|
|
m[ib] = 1
|
|
}
|
|
|
|
func shouldPanic(f func()) {
|
|
defer func() {
|
|
if recover() == nil {
|
|
panic("function should panic")
|
|
}
|
|
}()
|
|
f()
|
|
}
|