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