Skip to content

x/tools/go/analysis/passes/nilness: reports wrong diagnostic #73416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kfcss opened this issue Apr 17, 2025 · 2 comments
Closed

x/tools/go/analysis/passes/nilness: reports wrong diagnostic #73416

kfcss opened this issue Apr 17, 2025 · 2 comments
Labels
BugReport Issues describing a possible bug in the Go implementation. Tools This label describes issues relating to any tools in the x/tools repository.
Milestone

Comments

@kfcss
Copy link

kfcss commented Apr 17, 2025

Go version

go version go1.24.2 darwin/arm64

Output of go env in your module/workspace:

AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/<REDACTED>/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/<REDACTED>/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/8k/<REDACTED>/T/go-build3796509342=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/<REDACTED>/thirdparty/go-xtools/go.mod'
GOMODCACHE='/Users/<REDACTED>/go/pkg/mod'
GONOPROXY='none'
GONOSUMDB='css.com'
GOOS='darwin'
GOPATH='/Users/<REDACTED>/go'
GOPRIVATE='css.com'
GOPROXY='https://proxy.golang.org,<REDACTED>,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/<REDACTED>/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.2'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

I checked out commit f76b112f11ae44045f70b22a3d0dc0627f72ae10 of https://github.com/golang/tools.

Added the following to the end of https://github.com/golang/tools/blob/master/go/analysis/passes/nilness/testdata/src/a/a.go:

func f20(s1 *string) func() {
	return func() {
		isNilOrFoo := s1 == nil
		if !isNilOrFoo {
			isNilOrFoo = isNilOrFoo || *s1 == "foo"
		}
	}
}

Went to the the path go/analysis/passes/nilness and run go test.

What did you see happen?

I saw a diagnostic reported.

--- FAIL: Test (0.22s)
    analysistest.go:630: a/a.go:309:20: unexpected diagnostic: impossible condition: non-nil == nil

What did you expect to see?

No diagnostic should be reported.

If isNilOrFoo = isNilOrFoo || *s1 == "foo" is changed to isNilOrFoo = *s1 == "foo" no diagnostic is reported.

In fact isNilOrFoo is known to be false in isNilOrFoo || *s1 == "foo", which is probably the cause of the diagnostic. But it is very confusing that a diagnostic is reported on s1 == nil.

I don't know how this could be improved, but wanted to provide this as a test case as it caused confusion.

@gopherbot gopherbot added the Tools This label describes issues relating to any tools in the x/tools repository. label Apr 17, 2025
@gopherbot gopherbot added this to the Unreleased milestone Apr 17, 2025
@gabyhelp gabyhelp added the BugReport Issues describing a possible bug in the Go implementation. label Apr 17, 2025
@adonovan
Copy link
Member

This is a dup of #70381; see #70381 (comment) for explanation. In short,
the analyzer can't distinguish the actual program:

func f20(s1 *string) func() {
	return func() {
		isNilOrFoo := s1 == nil
		if !isNilOrFoo {
			isNilOrFoo = isNilOrFoo || *s1 == "foo"
		}
	}
}

from this alternative program:

func f20(s1 *string) func() {
	return func() {
		isNilOrFoo := s1 == nil
		if !isNilOrFoo {
			isNilOrFoo = s1 == nil || *s1 == "foo"
		}
	}
}

because the SSA representation for both is essentially identical. This causes it to report an error for what it thinks is the second occurrence of the s1 == nil condition in the second program, which would be a correct diagnostic---except that the s1 == nil.

The fix is to record additional bookkeeping in the SSA representation (such as enabling the GlobalDebug flag, but that's too expensive). Needs some careful thought. Apologies for the confusion.

I'm going to close this issue as a dup, but mention it from the canonical issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BugReport Issues describing a possible bug in the Go implementation. Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests

4 participants