1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package nilness inspects the control-flow graph of an SSA function 6 // and reports errors such as nil pointer dereferences and degenerate 7 // nil pointer comparisons. 8 // 9 // # Analyzer nilness 10 // 11 // nilness: check for redundant or impossible nil comparisons 12 // 13 // The nilness checker inspects the control-flow graph of each function in 14 // a package and reports nil pointer dereferences, degenerate nil 15 // pointers, and panics with nil values. A degenerate comparison is of the form 16 // x==nil or x!=nil where x is statically known to be nil or non-nil. These are 17 // often a mistake, especially in control flow related to errors. Panics with nil 18 // values are checked because they are not detectable by 19 // 20 // if r := recover(); r != nil { 21 // 22 // This check reports conditions such as: 23 // 24 // if f == nil { // impossible condition (f is a function) 25 // } 26 // 27 // and: 28 // 29 // p := &v 30 // ... 31 // if p != nil { // tautological condition 32 // } 33 // 34 // and: 35 // 36 // if p == nil { 37 // print(*p) // nil dereference 38 // } 39 // 40 // and: 41 // 42 // if p == nil { 43 // panic(p) 44 // } 45 // 46 // Sometimes the control flow may be quite complex, making bugs hard 47 // to spot. In the example below, the err.Error expression is 48 // guaranteed to panic because, after the first return, err must be 49 // nil. The intervening loop is just a distraction. 50 // 51 // ... 52 // err := g.Wait() 53 // if err != nil { 54 // return err 55 // } 56 // partialSuccess := false 57 // for _, err := range errs { 58 // if err == nil { 59 // partialSuccess = true 60 // break 61 // } 62 // } 63 // if partialSuccess { 64 // reportStatus(StatusMessage{ 65 // Code: code.ERROR, 66 // Detail: err.Error(), // "nil dereference in dynamic method call" 67 // }) 68 // return nil 69 // } 70 // 71 // ... 72 package nilness 73