package pkg import ( "errors" "os/exec" ) type T struct{ x *int } func fn1() *int { return nil } func fn2() (int, *int, int) { return 0, nil, 0 } func fn3() (int, error) { return 0, nil } func fn4() error { return nil } func gen1() interface{} { // don't flag, returning a concrete value return 0 } func gen2() interface{} { // don't flag, returning a concrete value return &T{} } func gen3() interface{} { // flag, always returns a typed value m := map[int]*int{} return m[0] } func gen4() (int, interface{}, *int) { // flag ret[1], always a typed value m := map[int]*int{} return 0, m[0], nil } func gen5() interface{} { // flag, propagate gen3 return gen3() } func gen6(b bool) interface{} { // don't flag, sometimes returns untyped nil if b { m := map[int]*int{} return m[0] } else { return nil } } func gen7() interface{} { // flag, always returns a typed value return fn1() } func gen8(x *int) interface{} { // flag if x == nil { return x } return x } func gen9() interface{} { // flag var x *int return x } func gen10() interface{} { // flag var x *int if x == nil { return x } return errors.New("") // This is a tricky one. we should flag this, because it never // returns a nil error, but if errors.New could return untyped // nils, then we shouldn't flag it. we need to consider the // implementation of the called function. } func gen11() interface{} { // don't flag, we sometimes return untyped nil if true { return nil } else { return (*int)(nil) } } func gen12(b bool) interface{} { // flag, all branches return typed nils var x interface{} if b { x = (*int)(nil) } else { x = (*string)(nil) } return x } func gen13() interface{} { // flag, always returns a typed value _, x, _ := fn2() return x } func gen14(ch chan *int) interface{} { // flag return <-ch } func gen15() interface{} { // flag t := &T{} return t.x } var g *int = new(int) func gen16() interface{} { // don't flag. returning a global is akin to returning &T{}. return g } func gen17(x interface{}) interface{} { // don't flag if x != nil { return x } return x } func gen18() (int, error) { // don't flag _, err := fn3() if err != nil { return 0, errors.New("yo") } return 0, err } func gen19() (out interface{}) { // don't flag if true { return (*int)(nil) } return } func gen20() (out interface{}) { // don't flag if true { return (*int)(nil) } return } func gen21() error { if false { return (*exec.Error)(nil) } return fn4() } func gen22() interface{} { if true { return g } return (*int)(nil) } func test() { _ = gen1() == nil _ = gen2() == nil _ = gen3() == nil // want `never true` { _, r2, r3 := gen4() _ = r2 == nil // want `never true` _ = r3 == nil } _ = gen5() == nil // want `never true` _ = gen6(false) == nil _ = gen7() == nil // want `never true` _ = gen8(nil) == nil // want `never true` _ = gen9() == nil // want `never true` _ = gen10() == nil // want `never true` _ = gen11() == nil _ = gen12(true) == nil // want `never true` _ = gen13() == nil // want `never true` _ = gen14(nil) == nil // want `never true` _ = gen15() == nil // want `never true` _ = gen16() == nil _ = gen17(nil) == nil { _, r2 := gen18() _ = r2 == nil } _ = gen19() == nil _ = gen20() == nil _ = gen21() == nil _ = gen22() == nil // want `never true` }