Repository navigation
Description
staticcheck version
$ staticcheck -version
staticcheck 2026.1 (v0.7.0)staticcheck -debug.version
Details
$ staticcheck -debug.version
staticcheck 2026.1 (v0.7.0)
Compiled with Go version: go1.25.8
Main module:
honnef.co/go/tools@v0.7.0 (sum: h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU=)
Dependencies:
github.com/BurntSushi/toml@v1.4.1-0.20240526193622-a339e1f7089c (sum: h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=)
golang.org/x/exp/typeparams@v0.0.0-20231108232855-2478ac86f678 (sum: h1:1P7xPZEwZMoBoz0Yze5Nx2/4pxj6nw9ZqHWXqP0iRgQ=)
golang.org/x/mod@v0.31.0 (sum: h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=)
golang.org/x/sync@v0.19.0 (sum: h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=)
golang.org/x/tools@v0.40.1-0.20260108161641-ca281cf95054 (sum: h1:CHVDrNHx9ZoOrNN9kKWYIbT5Rj+WF2rlwPkhbQQ5V4U=)go version
$ go version
go version go1.27.2 windows/amd64go env
Details
set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=1
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=
set GOAMD64=v1
set GOARCH=amd64
set GOAUTH=netrc
set GOBIN=C:\Users\Admin\go\bin
set GOCACHE=C:\Users\Admin\AppData\Local\go-build
set GOCACHEPROG=
set GODEBUG=
set GOENV=C:\Users\Admin\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOGCCFLAGS=-m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\Admin\AppData\Local\Temp\go-build606148118=/tmp/go-build -gno-record-gcc-switches
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMOD=C:\Users\Admin\AppData\Local\Temp\qf1003-tmpl\go.mod
set GOMODCACHE=C:\Users\Admin\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPACKAGESDRIVER=
set GOPATH=C:\Users\Admin\go
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTELEMETRY=local
set GOTELEMETRYDIR=C:\Users\Admin\AppData\Roaming\go\telemetry
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.27.2
set GOWORK=
set PKG_CONFIG=pkg-configExactly which command I ran
QF1003 is a quickfix analyzer, and cmd/staticcheck only registers quickfix analyzers behind a debug flag, so the check is invisible without it:
$ staticcheck -checks=QF1003 -debug.run-quickfix-analyzers ./...
repro.go:6:2: could use tagged switch on nil (QF1003)Output of the command and what is wrong with it
The diagnostic itself is correct, but the fix that QF1003 offers does not
775C
compile. This version of the CLI cannot apply fixes (-fix is not a flag):
$ staticcheck -fix ./...
flag provided but not defined: -fix
Usage: staticcheck [flags] [packages]
Flags:
-checks checks
Comma-separated list of checks to enable. (default "inherit")
-explain check
Print description of check
-f format
Output format (valid choices are 'stylish', 'text' and 'json') (default text)
-fail checks
Comma-separated list of checks that can cause a non-zero exit status. (default "all")
-go version
Target Go version in the format '1.x', or the literal 'module' to use the module's Go version (default "module")
-list-checks
List all available checks
-matrix
Read a build config matrix from stdin
-merge
Merge results of multiple Staticcheck runs
-show-ignored
Don't filter ignored diagnostics
-tags build tags
List of build tags
-tests
Include tests (default true)
-version
Print version and exit
For help about specifying packages, see 'go help packages'I therefore applied the suggested edit through gopls v0.24.0, which vendors honnef.co/go/tools and exposes quickfixes as code actions:
Details
$ gopls -v version
Build info
----------
golang.org/x/tools/gopls v0.24.0$ gopls codeaction -exec -write -kind=quickfix -title='Replace with tagged switch' ./repro.goThe resulting file:
// Package qf1003repro demonstrates the QF1003 suggestion.
package qf1003repro
// Record stores rating under name and reports the first error seen.
func Record(err, firstErr error, ratings map[string]int, name string, rating int) error {
switch nil {
case err:
ratings[name] = rating
case firstErr:
firstErr = err
}
return firstErr
}and the compile error it produces:
$ go build ./...
# example.com/qf1003repro
.\repro.go:6:9: use of untyped nil in switch expressionnil has no default type, so it is not a valid switch tag. The suggestion is not semantically convertible either: the second condition compares nil against a different variable (firstErr), so the two conditions share no usable operand. Using the right-hand operand as the tag would compile but change behaviour.
Cause
quickfix/qf1003/qf1003.go reuses the first comparison's left-hand operand as the switch tag without checking whether it is the predeclared nil:
x = pair[0].Xand renders it verbatim:
edits := []analysis.TextEdit{edit.ReplaceWithString(edit.Range{ifstmt.If, ifstmt.If}, fmt.Sprintf("switch %s {\n", report.Render(pass, x)))}Where the code is (embedded)
module example.com/qf1003repro
go 1.24// Package qf1003repro demonstrates the QF1003 suggestion.
package qf1003repro
// Record stores rating under name and reports the first error seen.
func Record(err, firstErr error, ratings map[string]int, name string, rating int) error {
if nil == err {
ratings[name] = rating
} else if nil == firstErr {
firstErr = err
}
return firstErr
}Suggested fix
Skip the suggestion when the common operand is the untyped nil, i.e. an *ast.Ident with Name == "nil" and Obj == nil.
Notes on reproducing
- The quickfix analyzers must be enabled with
-debug.run-quickfix-analyzers; otherwise-list-checksdoes not list QF checks,-explain QF1003reportsCouldn't find check QF1003, and-checks=alldoes not report it. - The module's
godirective must not exceed the Go version staticcheck was built with (go1.25.8). Withgo 1.26the run fails withpackage requires newer Go version go1.26 (application built with go1.25). - Reading
quickfix/qf1003/qf1003.goat tag2026.2.2(v0.8.2) shows the same unchecked assignment and the same rendering. I did not run that release, so that observation comes from the source only.
Related
The same text edit also drops indentation, which the source already notes with FIXME this edit forces the first case to begin in column 0 because we ignore indentation. try to fix that., directly above the edits construction; every affected file then needs gofmt. I did not open a separate report for it, since it is already tracked in the source.
Occurred in the wild
https://github.com/siyuan-note/siyuan/blob/dev/kernel/model/bazaar_rating.go uses if nil == err { ... } else if nil == firstErr { ... }.
Activity