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

(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; 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 ./...

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).