gopls version
golang.org/x/tools v0.32.0 // indirect
golang.org/x/tools/gopls v0.18.1 // indirect
go env
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='snip/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='snip/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2682111243=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='snip/go.mod'
GOMODCACHE='snip/go/pkg/mod'
GONOPROXY='snip'
GONOSUMDB='*'
GOOS='linux'
GOPATH='snip/go'
GOPRIVATE='snip'
GOPROXY='snip'
GOROOT='snip/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.2.linux-amd64'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='snip/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='snip/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.2.linux-amd64/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.2'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
go tool modernize --fix ./...
What did you see happen?
# golang.org/x/tools/gopls/internal/analysis/modernize
vendor/golang.org/x/tools/gopls/internal/analysis/modernize/bloop.go:167:29: c.Ancestors undefined (type cursor.Cursor has no field or method Ancestors)
vendor/golang.org/x/tools/gopls/internal/analysis/modernize/rangeint.go:156:15: cur.Edge undefined (type cursor.Cursor has no field or method Edge)
vendor/golang.org/x/tools/gopls/internal/analysis/modernize/rangeint.go:159:15: cur.Edge undefined (type cursor.Cursor has no field or method Edge)
vendor/golang.org/x/tools/gopls/internal/analysis/modernize/splitseq.go:55:30: curRange.Edge undefined (type cursor.Cursor has no field or method Edge)
vendor/golang.org/x/tools/gopls/internal/analysis/modernize/testingcontext.go:113:26: curFunc.Edge undefined (type cursor.Cursor has no field or method Edge)
What did you expect to see?
no errors :)
Editor and settings
No response
Logs
No response
Comment From: corani
Release of x/tools@v0.32.0
has broken modernize
. Version on master seems already fixed, could this be released ASAP?
Comment From: gabyhelp
Related Issues
- x/tools/gopls: automate daily updates of gopls/go.mod #34952 (closed)
- x/tools/gopls: references doesn't work properly. #60676 (closed)
- x/tools/gopls/internal/analysis/modernize: Panic in modernize/sortslice.go #71786 (closed)
- x/tools/gopls: \<DESCRIBE THE PROBLEM> #40020 (closed)
- x/tools/gopls: \<DESCRIBE THE PROBLEM> #40031 (closed)
- x/tools/gopls: \<DESCRIBE THE PROBLEM> #39999 (closed)
- x/tools/gopls: \<DESCRIBE THE PROBLEM> #40030 (closed)
- x/tools/gopls: \<DESCRIBE THE PROBLEM> #39995 (closed)
- x/tools/gopls: \<DESCRIBE THE PROBLEM> #40087 (closed)
- x/tools/gopls: \<DESCRIBE THE PROBLEM> #40064 (closed)
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: adonovan
go tool modernize --fix ./...
Where did this command come from? (Is there some incorrect documentation recommending it?)
go tool
locates executables of the Go toolchain; but modernize
is an internal command of the golang.org/x/tools/gopls module. The command you want is this (or go install
followed by just modernize
):
$ go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...
Release of x/tools@v0.32.0 has broken modernize. Version on master seems already fixed, could this be released ASAP?
What command did you run? Unless you have git clone of x/tools, you cannot build versions of gopls that are not on a release branch.
Comment From: corani
Where did this command come from?
From go get -tool golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest
.
I use this to pin the exact version of tools I'm using in our CI/CD pipelines, to ensure reproducible builds. Previously I was using a sub-module with a tools.go
to pin the versions, I've recently changed this to use the new tool
directive in the main go.mod
.
Dependency updates are coming from Renovate, which is trying to update x/tools
now, most likely due to a similar dependency on golang.org/x/tools/cmd/stringer
.
Comment From: enckse
I've also run into this issue (I used go get -tool golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest
much like @corani ).
Where did this command come from? (Is there some incorrect documentation recommending it?)
Specifically wanted to add to this, I don't think there is any documentation necessarily recommending to use go get -tool ...
and go tool modernize ...
(in this case) as much as it is very handy to be able to version the modernize
command along with anything else of interest in go.mod
and go get -tool
certainly didn't stop me.
Comment From: alexaandru
Me too. I used go get tool
to update the tools (which included modernize) and then modernize was breaking as above.
Comment From: adonovan
@matloob, is this an interaction between vendoring of x/tools in goroot and the new go get -tool
/go tool
feature?
Comment From: corani
To reproduce:
$ cd $(mktemp -d)
$ go mod init example
go: creating new go.mod: module example
$ go get -tool golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest
go: added golang.org/x/mod v0.23.0
go: added golang.org/x/sync v0.11.0
go: added golang.org/x/tools v0.30.1-0.20250221230316-5055f70f240c
go: added golang.org/x/tools/gopls v0.18.1
$ go get -tool golang.org/x/tools/cmd/stringer@latest
go: upgraded golang.org/x/mod v0.23.0 => v0.24.0
go: upgraded golang.org/x/sync v0.11.0 => v0.13.0
go: upgraded golang.org/x/tools v0.30.1-0.20250221230316-5055f70f240c => v0.32.0
$ go tool modernize
# golang.org/x/tools/gopls/internal/analysis/modernize
$HOME/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/analysis/modernize/bloop.go:167:29: c.Ancestors undefined (type cursor.Cursor has no field or method Ancestors)
$HOME/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/analysis/modernize/rangeint.go:156:15: cur.Edge undefined (type cursor.Cursor has no field or method Edge)
$HOME/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/analysis/modernize/rangeint.go:159:15: cur.Edge undefined (type cursor.Cursor has no field or method Edge)
$HOME/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/analysis/modernize/splitseq.go:55:30: curRange.Edge undefined (type cursor.Cursor has no field or method Edge)
$HOME/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/analysis/modernize/testingcontext.go:113:26: curFunc.Edge undefined (type cursor.Cursor has no field or method Edge)
$ cat go.mod
module example
go 1.24.1
tool (
golang.org/x/tools/cmd/stringer
golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize
)
require (
golang.org/x/mod v0.24.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/tools v0.32.0 // indirect
golang.org/x/tools/gopls v0.18.1 // indirect
)
Note: stringer
is just one example, but many other modules cause this breakage due to a dependency on x/tools@v0.32.0
(for example: github.com/mvdan/gofumpt@v0.8.0
)
Comment From: thepudds
Where did this command come from? (Is there some incorrect documentation recommending it?)
go tool
locates executables of the Go toolchain; butmodernize
is an internal command of the golang.org/x/tools/gopls module. The command you want is this (orgo install
followed by justmodernize
):$ go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...
Hi @adonovan, I suspect the new go tool
support in Go 1.24 is so convenient that people might over use it.
I think the reason for the behavior in @corani's example in https://github.com/golang/go/issues/73279#issuecomment-2801300318 is briefly explained in the documentation:
Requirements needed to satisfy tool dependencies behave like any other requirements in your module graph. They participate in minimal version selection [...]
It would probably be good to better document some of the alternatives to using go tool
. See for example #71663 and https://go.dev/cl/648578, which seem like they need some more discussion to work out what we want to do.
Comment From: adonovan
Thanks @corani and @thepudds, that explains it. The issue here is that the modernize command, currently (but not fundamentally) part of the gopls module, is governed by the gopls release process, and you can't just upgrade the x/tools package to a later one, as happens when installing stringer, because the gopls release branch needs a particular version and x/tools does not present a stable internal API to gopls. In short, no-one should ever add gopls as a module dependency, and that means you cannot use go get -tool
with gopls. I will update the documentation to make this clear.
@matloob mentioned that there was a discussion during the design of the -tool
feature as to whether each tool command should have its own constraint system, or whether all of them should be subject to a single set of constraints. This behavior is a consequence of using a single constraint system. He also mentioned that one could also argue that the way gopls uses x/tools is an abuse of semantic versioning.
Comment From: gopherbot
Change https://go.dev/cl/665636 mentions this issue: gopls: warn against using go get -tool with gopls
Comment From: gopherbot
Change https://go.dev/cl/665637 mentions this issue: gopls: improve warning against using go get -tool with gopls
Comment From: findleyr
@adonovan is there anything actionable to do here, other than improve documentation?
If not, let's close this as Won't Fix (unfortunate).