The problem is that nil can be a perfectly acceptable receiver, and sometimes (as documented for the function/method) you may get a value
and and error.
For example, the documentation for an io.Reader states:
Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.
Granted, n is an int and not a pointer, but it is wonderful example of getting back a value and an error.
I think static analysis will not help much. There is no way in the language to know if a nil value is valid or not. Consider the simple code of:
var p *SomeType
p.Method()
The compiler can make no assumptions about p since Method may indeed handle a nil receiver. Yes, the compiler could reach down into Method and check if all paths eventually lead to an unrecovered panic, but as long as one path does not, the nil may be valid. I am not sure the (very small) gain is worth the effort here.
I would be much happier if the compiler could figure out that given:
const showDebug = false
var debug(f string, v ...interface{}) {
if showDebug {
fmt.Printf(f, v...)
}
}
and then
debug("%s: %v\n", foo.Name, foo.SomeExpensiveCall())
that if foo.SomeExpensiveCall() has no observable side effects (other than returning a value) that it needn't even be called as it's value will never be productively used.
-Paul