| // 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) | |
| // gc 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() | |
| } |