Go version

go version go1.25rc1 linux/arm64

Output of go env in your module/workspace:

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=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3464693305=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/root/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_arm64'
GOVCS=''
GOVERSION='go1.25rc1'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

While testing our code with go1.25rc1; https://github.com/moby/moby/pull/50313#issuecomment-3029256686, gotestsum failed to compile with an errorr in golang.org/x/tools v0.19.0

Note that golang.org/x/tools v0.19.0 is a pretty old version, but it probably should not be expected for code to fail.

What did you see happen?

docker run --rm golang:1.25rc1 sh -c 'go install gotest.tools/gotestsum@v1.12.0'
go: downloading gotest.tools/gotestsum v1.12.0
go: downloading github.com/dnephin/pflag v1.0.7
go: downloading github.com/fatih/color v1.16.0
go: downloading github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
go: downloading golang.org/x/tools v0.19.0
go: downloading github.com/fsnotify/fsnotify v1.7.0
go: downloading golang.org/x/sys v0.18.0
go: downloading github.com/bitfield/gotestdox v0.2.2
go: downloading golang.org/x/sync v0.6.0
go: downloading golang.org/x/term v0.18.0
go: downloading github.com/mattn/go-colorable v0.1.13
go: downloading github.com/mattn/go-isatty v0.0.20
go: downloading golang.org/x/text v0.14.0
go: downloading golang.org/x/mod v0.16.0
# golang.org/x/tools/internal/tokeninternal
pkg/mod/golang.org/x/tools@v0.19.0/internal/tokeninternal/tokeninternal.go:64:9: invalid array length -delta * delta (constant -256 of type int64)

Looks to be here; https://github.com/golang/tools/blob/v0.19.0/internal/tokeninternal/tokeninternal.go#L62-L64

// If the size of token.FileSet changes, this will fail to compile.
const delta = int64(unsafe.Sizeof(tokenFileSet{})) - int64(unsafe.Sizeof(token.FileSet{}))
var _ [-delta * delta]int

What did you expect to see?

No failures

Comment From: rittneje

Isn't this due to the exact situation described in the comment? The structure of token.FileSet changed in 1.25rc1, and thus the compile-time failure is intentional.

Comment From: seankhliao

x/tools generally needs to be new enough to support newer versions of go.

Comment From: zigo101

btw, @thaJeztah there is a simpler trick to do the assertion.

var _ = "a"[unsafe.Sizeof(tokenFileSet{}) - unsafe.Sizeof(token.FileSet{})]

[edit] Aha, that is in the tool project instead of moby. :D

Comment From: Lin-Ziyue

This also happened in win11 go1.25.0 while I was downloading fyne

Comment From: andydotxyz

Yup, we see this in our CI too. We have slightly older golang.org/x deps because we are trying to maintain 1.19 as a minimum required Go version…

Comment From: findleyr

This is our mistake, sorry. A bit of background:

  • x/tools used unsafe to work around some major performance problems with the token.FileSet datastructure. This fix has since been upstreamed in #73205, so that we no longer need to use unsafe.
  • The tokeninternal package, which contained this unsafe workaround intended only for gopls, had another use in x/tools at v0.19.0. An unrelated function in the package (not the one that uses unsafe) was used by the gcimporter package, which is reachable through the public API of x/tools. This unintended edge was also subsequently removed, but not before some projects depended on affected versions.

So this was a latent bug in x/tools, which has since been fixed, but is now being encountered in projects depending on the affected versions. Apologies for the breakage.

Comment From: jamietanna

Would there be any appetite to backport a patch of this to an older version of /x/tools?

In recent releases the minimum go source directive has been bumped by /x/tools.

As noted by Andy above, there are some of us who are trying to keep tooling still working on lower Go versions (for instance, in oapi-codegen we're trying to stick with 1.22

If we upgrade /x/tools to fix some folks' builds on Go 1.25, we're forcing everyone to need to build with Go 1.24

If we could backport this fix, that'd allow us to choose an older tag with maybe Go 1.22 (or 1.23) compatibility to reduce the chain of events forcing everyone else to upgrade too

Comment From: andydotxyz

Thanks @jamietanna a solid plan.

For context the Fyne library wants to always work with the versions current in the popular package managers. Not everyone manages Go using Go or direct downloads and if their system is completely up to date then ideally their apps should continue to compile without needing toolchain upgrades.

Comment From: andydotxyz

From my digging it seems to be the case that:

If your golang.org/x/tools dependency is more than 2 months old your code will fail to compile with Go 1.25!!!

Comment From: Lin-Ziyue

I use go 1.24 as an alternative and the then latest x/tools package runs well .

Comment From: Lin-Ziyue

@andydotxyz yesterday when I use go 1.25.0 with the latest version ,I still got a return"invalid array length -delta * delta (constant -256 of type int64)" .Pay attention ,I also check the version personally .

Comment From: andydotxyz

Please print the whole error. That code is not present in the latest version so something went wrong at your end. Or it's ANOTHER dependency that has the same problem.

Comment From: findleyr

Reopening because this is a bad, unintentional breakage, and we should reconsider possible mitigations.

To summarize: an optimization to the token.FileSet struct in 1.25 breaks older versions of the x/tools/internal/tokeninternal package that used unsafe to work around certain related performance problems detailed in #73205. In my initial analysis above (https://github.com/golang/go/issues/74462#issuecomment-3192864978), I was unfortunately mistaken: the GetLines function is used indirectly by x/tools/go/gcexportdata.Write, and also contains this unsafe trick.

This shouldn't have happened: x/tools should not depend on the internal layout of the token.FileSet struct, and while we need to analyze the impact of this bug, it seems quite bad: as @andydotxyz analyzed, this problem is present in versions of x/tools as recent as 2mo old. Fortunately, among packages in x/tools, go/gcexportdata is infrequently used.

We should investigate potential mitigations. It's gnarly, but here are some potential paths forward:

  1. Revert https://go.dev/cl/675736 for go 1.25.1.
  2. Patch older versions of x/tools (suggested by @jamietanna above). This may be combinatorially complex (there may be many affected versions), and could lead to painful interactions with MVS, but might still be a safe path forward if we retract all the bad versions.
  3. Simply pad the go/token.FileSet struct to be the same size in 1.25 as it was in 1.24, and turn a compile-time error into a (likely unreachable) runtime error. This would have been more viable if not for the reachability of tokeninternal.GetLines through the x/tools/go/gcexportdata API.

Comment From: jamietanna

Thanks @findleyr!

Happy for this to be a separate issue, but it would also be good to see if it's possible to try and keep the go directive (for Go source version compatibility) lower than "stable" and "oldstable".

As per discussion (0 2) on the #cup-o-go channel on Gopher Slack, the bumping of the go directive then requires all dependent modules to also bump theirs, which has a cascading effect.

For modules such as oapi-codegen (or Fyne as Andy mentioned), we try and keep the minimum Go source version as low as possible.

Comment From: findleyr

Some analysis:

> for v in $(go list --m --versions -f "{{range .Versions}}{{.}} {{end}}" golang.org/x/tools); do echo -n "$v "; go mod edit -require=golang.org/x/tools@$v; go mod tidy; go build . 2>/dev/null && echo "ok" || echo "broken"; done
v0.1.0 ok
v0.1.1 ok
v0.1.2 ok
v0.1.3 ok
v0.1.4 ok
v0.1.5 ok
v0.1.6 broken
v0.1.7 ok
v0.1.8 ok
v0.1.9 ok
v0.1.10 ok
v0.1.11 ok
v0.1.12 ok
v0.2.0 ok
v0.3.0 ok
v0.4.0 ok
v0.5.0 ok
v0.6.0 ok
v0.7.0 ok
v0.8.0 broken
v0.9.0 broken
v0.9.1 broken
v0.9.2 broken
v0.9.3 broken
v0.10.0 broken
v0.11.0 broken
v0.11.1 broken
v0.12.0 broken
v0.13.0 broken
v0.14.0 broken
v0.15.0 broken
v0.16.0 broken
v0.16.1 broken
v0.17.0 broken
v0.18.0 broken
v0.19.0 broken
v0.20.0 broken
v0.21.0 broken
v0.22.0 broken
v0.23.0 broken
v0.24.0 broken
v0.25.0 broken
v0.26.0 ok
v0.27.0 ok
v0.28.0 ok
v0.29.0 ok
v0.30.0 ok
v0.31.0 ok
v0.32.0 ok
v0.33.0 ok
v0.34.0 ok
v0.35.0 ok
v0.36.0 ok

This query indicated the build is broken on the interval [v0.8.0, v0.25.0]. It was effectively fixed in v0.26.0, which was tagged on October 4th, 2024, when the GetLines method was replaces with token.File.Lines. @andydotxyz this doesn't quite line up with your analysis in https://github.com/golang/go/issues/74462#issuecomment-3193595799. Can you please confirm that your build succeeds with x/tools@v0.26.0?

I wrote a little script to ensure that the tokeninternal package is wholly unreachable from the public API of x/tools, and can use this to verify the fix, if we decide to patch.

Comment From: findleyr

@jamietanna it looks like v0.26.0 supports go 1.22, if you want to upgrade to that.

The last x/tools version that supports down to go 1.19 is v0.24.0. A minimal fix might be to tag v0.24.1, and retract [v0.8.0, v0.24.0] as well as v0.25.0.

Comment From: findleyr

The team discussed in chat, and here is our plan:

  1. We're going to start by tagging x/tools@v0.24.1 and x/tools@v0.25.1 with fixes. We'd like to minimize the number of new versions that are created, to limit complexity. This hopefully also avoids problems with MVS: if you update to v0.24.1, there is only one problematic version that you might be upgraded (v0.25.0). Since v0.24.x supports go1.19, we hope that this offers a mitigation path for most users, even if they are still supporting older Go versions.
  2. We will probably retract [v0.8.0, v0.24.0] and v0.25.0, though this is unlikely to make much difference as warnings only occur in limited scenarios, such as upgrading to a retracted version.
  3. We will probably also include a fix in go1.25.1, either by rolling back https://go.dev/cl/675736 or by padding the token.FileSet struct. However, we are not currently planning to expedite go1.25.1, which is currently scheduled for early September.

Please let me know if you have any feedback on this plan. I will create the new tags (step 1) later today or tomorrow.

Comment From: andydotxyz

Thanks @findleyr this is excellent, I appreciate you taking the time to consider how to smooth this over. The steps sound excellent, the 3rd would be good but for those following the ticket we can migrate and resolve our local issues with just 1.

As soon as there are tags pushed I will begin testing at our end and verify it's all resolved for Fyne :)

Comment From: gopherbot

Change https://go.dev/cl/697336 mentions this issue: [release-branch.0.24] internal/tokeninternal: move unsafe gopls code into gopls

Comment From: gopherbot

Change https://go.dev/cl/697337 mentions this issue: [release-branch.0.24] gopls: fix the build with go1.25

Comment From: gopherbot

Change https://go.dev/cl/697335 mentions this issue: [release-branch.0.24] all: update codereview.cfg for release-branch.0.24

Comment From: findleyr

I've created the v0.24.1 tag. It was hard than expected, because x/tools tests are very sensitive to std changes.

go get golang.org/x/tools@v0.24.1

Will look into v0.25.1.

Comment From: gopherbot

Change https://go.dev/cl/697416 mentions this issue: [release-branch.0.25] internal/tokeninternal: move unsafe gopls code into gopls

Comment From: gopherbot

Change https://go.dev/cl/697415 mentions this issue: [release-branch.0.25] all: update codereview.cfg for release-branch.0.25

Comment From: gopherbot

Change https://go.dev/cl/697339 mentions this issue: [release-branch.0.25] gopls: fix the build with go1.25

Comment From: findleyr

v0.25.1 is now created as well:

go get golang.org/x/tools@v0.25.1

Reassigning to Alan to decide what we should do about https://go.dev/cl/675736 for go1.25.1. For what it's worth, upon analysis it would be possible to mitigate this by padding the token.FileSet struct, though that is of course a rather dirty solution.