1// run 2 3// Copyright 2019 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7// short-circuiting interface-to-concrete comparisons 8// will not miss panics 9 10package main 11 12import ( 13 "log" 14 "strings" 15) 16 17func main() { 18 var ( 19 x interface{} 20 p *int 21 s []int 22 l *interface{} 23 r []*int 24 ) 25 tests := []struct { 26 name string 27 errStr string 28 f func() 29 }{ 30 {"switch case", "", func() { 31 switch x { 32 case x.(*int): 33 } 34 }}, 35 {"interface conversion", "", func() { _ = x == x.(error) }}, 36 {"type assertion", "", func() { _ = x == x.(*int) }}, 37 {"out of bounds", "", func() { _ = x == s[1] }}, 38 {"nil pointer dereference #1", "", func() { _ = x == *p }}, 39 // TODO(mdempsky): Restore "nil pointer dereference" check. The Go 40 // spec doesn't mandate an order for panics (or even panic 41 // messages), but left-to-right is less confusing to users. 42 {"nil pointer dereference #2", "", func() { _ = *l == r[0] }}, 43 {"nil pointer dereference #3", "", func() { _ = *l == any(r[0]) }}, 44 } 45 46 for _, tc := range tests { 47 testFuncShouldPanic(tc.name, tc.errStr, tc.f) 48 } 49} 50 51func testFuncShouldPanic(name, want string, f func()) { 52 defer func() { 53 e := recover() 54 if e == nil { 55 log.Fatalf("%s: comparison did not panic\n", name) 56 } 57 if have := e.(error).Error(); !strings.Contains(have, want) { 58 log.Fatalf("%s: wrong panic message: have %q, want %q\n", name, have, want) 59 } 60 }() 61 f() 62} 63