-1

The following code causes a SIGSEGV error. Are there tools such as linters that can flag this bad logic?

package main

// Person is ...
type Person interface {
        M()
}

func main() {
        var i Person
        i.M()
}

golint does not detect this.

AcBap
  • 79
  • 1
  • 1
  • 10
  • Can you share what part of this you consider to be an invalid use? Is it the ability to call the method `M` on a nil `Person`? – nishanthshanmugham Nov 27 '20 at 18:54
  • 1
    It's "documented" in [the Tour of Go](https://tour.golang.org/methods/13) :-P – kostix Nov 27 '20 at 18:59
  • 1
    I, for one, have no idea except for vague feeling that the devs prefer "all or nothing" approach. What I mean is that while in _this_ case the analyzis does indeed appear sufficiently easy to implement, what about the following — `var i Person; i = &SomeTypeWithMethodM{}; /* 100 lines of code */ i = nil; /* 100 lines of code */ i.M()`? It could be possible to implement in mostly the same style as escape analysis: have a complexity threshold after which the compiler gives up. But that could mean it would flag as errors only _trivial_ cases (such as yours), … – kostix Nov 27 '20 at 19:09
  • 1
    … and non-trivial cases would not produce any error, essentially creating in a programmer a false sense of confidence. But this is different from a failure to completely trace a variable's lifetime during esacpe analysis: if the latter fails, the compiler pessimistically generates less-than-optimal code, _which is still correct_ according to the spec, just less effective. – kostix Nov 27 '20 at 19:11
  • 1
    @nishanthshanmugham, by "obviously bad use," I meant "obviously bad logic." I'd thought it's obvious that "i" is *nil* value here. – AcBap Nov 27 '20 at 19:29
  • @kostix, nil pointer is a notorious source of run-time errors, and thus, I'd hope, the Go tooling would try to help whenever possible. – AcBap Nov 27 '20 at 19:39
  • @AcBap Does _any_ other language detect NPE at compile time? – Iblisto Nov 27 '20 at 20:26
  • @Iblisto, I'm not aware of any! As I indicated in your other comment that this could be a "feature" request. Since Go eliminates memory leak problem, I was a bit disappointed that this issue occurs, and thus wanted to learn more about it. At the same time, I was also looking for the tools that could help. – AcBap Nov 27 '20 at 20:53

2 Answers2

1

Because compiler doesn't have knowledge of what the underlying concrete type i has at compile time. Consider this example:

func main() {
        var i Person
        if gender == "woman" {
                i = &Woman{}
        }
        i.M()
}

Because compiler doesn't know the value of gender at compile time, it also doesn't know whether &Woman{} is assigned to i or is left as a zero value of Person interface, which is nil.

Iblisto
  • 309
  • 2
  • 7
  • The OP had presented a specifically trivial case which is — ostensibly — easy to detect. – kostix Nov 27 '20 at 19:12
  • @kostix I see your point. Well it's just not part of compiler's job - sounds more like you're asking for a "feature request" to the compiler here. This applies to any languages, not just Go. That said, I'm sure there are linters that _warn_ you for the code that can possibly produce NullPointerException in some languages. – Iblisto Nov 27 '20 at 19:35
0

This isn’t an invalid use. The variable i is bound to an interface Person whose value is nil.

Accessing a field or calling a method on a nil interface value will result in a panic, as observed.

nishanthshanmugham
  • 2,967
  • 1
  • 25
  • 29
  • This _is_ relevant: if the underlying type wasn't `nil`, it would be OK to perform the call as the implementation of `M` of that type could gracefully deal with `nil` receiver value. – kostix Nov 27 '20 at 19:02