]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: don't write own toolchain line when updating go line
authorMichael Matloob <matloob@golang.org>
Mon, 10 Mar 2025 17:32:23 +0000 (13:32 -0400)
committerMichael Matloob <matloob@golang.org>
Wed, 12 Mar 2025 18:44:56 +0000 (11:44 -0700)
The Go command had a behavior of writing its own toolchain name when
updating the go line in a go.mod (for example when a user runs go get
go@version). This behavior was often undesirable and the toolchain line
was often removed by users before checking in go.mod files (including in
the x/ repos). It also led to user confusion.

This change removes that behavior. A toolchain line will not be added if
one wasn't present before. The toolchain line can still be removed
though: the toolchain line must be at least the go version, so if the go
version is increased above the toolchain version, the toolchain version
will be bumped up to that go version. Then the toolchain line will then
be dropped because go <version> implies toolchain <version>.

Making this change slightly hurts reproducability because future go
commands run on the go.mod file may be run with a different toolchain
than the one that used it, but that doesn't seem to be worth the
confusion the behavior resulted in.

We expect this change will not have negative consequences, but it could
be possible, and we would like to hear from any users that depended on
the previous behavior in case we need to roll it back before the
release.

Fixes #65847

Change-Id: Id795b7f762e4f90ba0fa8c7935d03f32dfc8590e
Reviewed-on: https://go-review.googlesource.com/c/go/+/656835
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/go/internal/modload/init.go
src/cmd/go/testdata/script/gotoolchain_modcmds.txt
src/cmd/go/testdata/script/mod_download_exec_toolchain.txt
src/cmd/go/testdata/script/mod_get_exec_toolchain.txt
src/cmd/go/testdata/script/mod_get_toolchain.txt
src/cmd/go/testdata/script/mod_import_toolchain.txt
src/cmd/go/testdata/script/mod_tidy_version.txt
src/cmd/go/testdata/script/mod_toolchain.txt
src/cmd/go/testdata/script/work_get_toolchain.txt
src/cmd/go/testdata/script/work_sync_toolchain.txt
src/cmd/go/testdata/script/work_use_toolchain.txt

index 5d01aedc2f3f8e5a96f61b3ed25e62b7d131e281..1ffe5052fb359026a9c903d1c1c54204fab5c485 100644 (file)
@@ -745,34 +745,25 @@ func UpdateWorkGoVersion(wf *modfile.WorkFile, goVers string) (changed bool) {
 
        wf.AddGoStmt(goVers)
 
-       // We wrote a new go line. For reproducibility,
-       // if the toolchain running right now is newer than the new toolchain line,
-       // update the toolchain line to record the newer toolchain.
-       // The user never sets the toolchain explicitly in a 'go work' command,
-       // so this is only happening as a result of a go or toolchain line found
-       // in a module.
-       // If the toolchain running right now is a dev toolchain (like "go1.21")
-       // writing 'toolchain go1.21' will not be useful, since that's not an actual
-       // toolchain you can download and run. In that case fall back to at least
-       // checking that the toolchain is new enough for the Go version.
-       toolchain := "go" + old
-       if wf.Toolchain != nil {
-               toolchain = wf.Toolchain.Name
-       }
-       if gover.IsLang(gover.Local()) {
-               toolchain = gover.ToolchainMax(toolchain, "go"+goVers)
-       } else {
-               toolchain = gover.ToolchainMax(toolchain, "go"+gover.Local())
+       if wf.Toolchain == nil {
+               return true
        }
 
-       // Drop the toolchain line if it is implied by the go line
+       // Drop the toolchain line if it is implied by the go line,
+       // if its version is older than the version in the go line,
        // or if it is asking for a toolchain older than Go 1.21,
        // which will not understand the toolchain line.
-       if toolchain == "go"+goVers || gover.Compare(gover.FromToolchain(toolchain), gover.GoStrictVersion) < 0 {
+       // Previously, a toolchain line set to the local toolchain
+       // version was added so that future operations on the go file
+       // would use the same toolchain logic for reproducibility.
+       // This behavior seemed to cause user confusion without much
+       // benefit so it was removed. See #65847.
+       toolchain := wf.Toolchain.Name
+       toolVers := gover.FromToolchain(toolchain)
+       if toolchain == "go"+goVers || gover.Compare(toolVers, goVers) < 0 || gover.Compare(toolVers, gover.GoStrictVersion) < 0 {
                wf.DropToolchainStmt()
-       } else {
-               wf.AddToolchainStmt(toolchain)
        }
+
        return true
 }
 
@@ -1833,22 +1824,7 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b
                toolchain = "go" + goVersion
        }
 
-       // For reproducibility, if we are writing a new go line,
-       // and we're not explicitly modifying the toolchain line with 'go get toolchain@something',
-       // and the go version is one that supports switching toolchains,
-       // and the toolchain running right now is newer than the current toolchain line,
-       // then update the toolchain line to record the newer toolchain.
-       //
-       // TODO(#57001): This condition feels too complicated. Can we simplify it?
-       // TODO(#57001): Add more tests for toolchain lines.
        toolVers := gover.FromToolchain(toolchain)
-       if wroteGo && !opts.DropToolchain && !opts.ExplicitToolchain &&
-               gover.Compare(goVersion, gover.GoStrictVersion) >= 0 &&
-               (gover.Compare(gover.Local(), toolVers) > 0 && !gover.IsLang(gover.Local())) {
-               toolchain = "go" + gover.Local()
-               toolVers = gover.FromToolchain(toolchain)
-       }
-
        if opts.DropToolchain || toolchain == "go"+goVersion || (gover.Compare(toolVers, gover.GoStrictVersion) < 0 && !opts.ExplicitToolchain) {
                // go get toolchain@none or toolchain matches go line or isn't valid; drop it.
                // TODO(#57001): 'go get' should reject explicit toolchains below GoStrictVersion.
index 1edd6d85a5e66c6884e9be4e645b613cd76cec8b..e6a45533bcfee28d7057949e7f2c5bdfaf556bf8 100644 (file)
@@ -21,7 +21,7 @@ stderr '^go: rsc.io/future@v1.0.0: module rsc.io/future@v1.0.0 requires go >= 1.
 go get .
 stderr '^go: module rsc.io/future@v1.0.0 requires go >= 1.999; switching to go1.999testmod$'
 stderr '^go: upgraded go 1.21 => 1.999$'
-stderr '^go: added toolchain go1.999testmod$'
+! stderr '^go: added toolchain'
 
 
 # Now, the various 'go mod' subcommands should succeed.
index 6cf863b28a28f6b16bcf38a8b9b1a9342713ae41..78b62aa7f0ae063cb5f69b2ba0fbff07f8baa8d3 100644 (file)
@@ -102,6 +102,4 @@ module example
 
 go 1.23
 
-toolchain go1.23.9
-
 require rsc.io/needall v0.0.1
index 497fe36f4045b0c9cce3aaf20ef92575d8058b34..79df80e841af694cddcc4a4a79165216a3a86b90 100644 (file)
@@ -9,7 +9,7 @@ stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
 ! stderr '\(running'
 stderr '^go: added rsc.io/needall v0.0.1'
 grep 'go 1.23' go.mod
-grep 'toolchain go1.23.9' go.mod
+! grep toolchain go.mod
 
 # GOTOOLCHAIN=min+auto should run the newer toolchain
 env GOTOOLCHAIN=go1.21+auto
@@ -19,7 +19,7 @@ stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
 ! stderr '\(running'
 stderr '^go: added rsc.io/needall v0.0.1'
 grep 'go 1.23' go.mod
-grep 'toolchain go1.23.9' go.mod
+! grep toolchain go.mod
 
 # GOTOOLCHAIN=go1.21 should NOT run the newer toolchain
 env GOTOOLCHAIN=go1.21
@@ -67,7 +67,7 @@ cp go.mod.new go.mod
 go get go@1.22rc1
 stderr '^go: updating go.mod requires go >= 1.22rc1; switching to go1.22.9$'
 stderr '^go: upgraded go 1.1 => 1.22rc1$'
-stderr '^go: added toolchain go1.22.9$'
+! stderr '^go: added toolchain$'
 
 # go get go@1.22.1 should use 1.22.1 exactly, not a later release.
 env GOTOOLCHAIN=local
@@ -80,7 +80,7 @@ cp go.mod.new go.mod
 go get go@1.22.1
 stderr '^go: updating go.mod requires go >= 1.22.1; switching to go1.22.9$'
 stderr '^go: upgraded go 1.1 => 1.22.1$'
-stderr '^go: added toolchain go1.22.9$'
+! stderr '^go: added toolchain$'
 
 # go get needgo122 (says 'go 1.22') should use 1.22.0, the earliest release we have available
 # (ignoring prereleases).
@@ -94,7 +94,7 @@ cp go.mod.new go.mod
 go get rsc.io/needgo122
 stderr '^go: upgraded go 1.1 => 1.22$'
 stderr '^go: rsc.io/needgo122@v0.0.1 requires go >= 1.22; switching to go1.22.9$'
-stderr '^go: added toolchain go1.22.9$'
+! stderr '^go: added toolchain$'
 
 # go get needgo1223 (says 'go 1.22.3') should use go 1.22.3
 env GOTOOLCHAIN=local
@@ -107,7 +107,7 @@ cp go.mod.new go.mod
 go get rsc.io/needgo1223
 stderr '^go: upgraded go 1.1 => 1.22.3$'
 stderr '^go: rsc.io/needgo1223@v0.0.1 requires go >= 1.22.3; switching to go1.22.9$'
-stderr '^go: added toolchain go1.22.9$'
+! stderr '^go: added toolchain$'
 
 # go get needgo124 (says 'go 1.24') should use go 1.24rc1, the only version available
 env GOTOOLCHAIN=local
@@ -120,7 +120,7 @@ cp go.mod.new go.mod
 go get rsc.io/needgo124
 stderr '^go: rsc.io/needgo124@v0.0.1 requires go >= 1.24; switching to go1.24rc1$'
 stderr '^go: upgraded go 1.1 => 1.24$'
-stderr '^go: added toolchain go1.24rc1$'
+! stderr '^go: added toolchain$'
 
 # The -C flag should not happen more than once due to switching.
 mkdir dir dir/dir
@@ -132,7 +132,7 @@ cp p.go dir/dir/p.go
 go get -C dir rsc.io/needgo124
 stderr '^go: rsc.io/needgo124@v0.0.1 requires go >= 1.24; switching to go1.24rc1$'
 stderr '^go: upgraded go 1.1 => 1.24$'
-stderr '^go: added toolchain go1.24rc1$'
+! stderr '^go: added toolchain1$'
 cmp go.mod.new go.mod
 cmp go.mod.new dir/dir/go.mod
 grep 'go 1.24$' dir/go.mod
index 758142d668f9c6bbf90f14c685fff633eff91f4c..87e84ae15ef9872d1380c1fc33a4cd5ed1c3739a 100644 (file)
@@ -7,28 +7,28 @@ cp go.mod.orig go.mod
 go get go
 stderr '^go: upgraded go 1.21 => 1.23.9$'
 grep 'go 1.23.9' go.mod
-grep 'toolchain go1.99rc1' go.mod
+! grep toolchain go.mod
 
 # go get go@1.23 should use the latest Go 1.23
 cp go.mod.orig go.mod
 go get go@1.23
 stderr '^go: upgraded go 1.21 => 1.23.9$'
 grep 'go 1.23.9' go.mod
-grep 'toolchain go1.99rc1' go.mod
+! grep toolchain go.mod
 
 # go get go@1.22 should use the latest Go 1.22
 cp go.mod.orig go.mod
 go get go@1.22
 stderr '^go: upgraded go 1.21 => 1.22.9$'
 grep 'go 1.22.9' go.mod
-grep 'toolchain go1.99rc1' go.mod
+! grep toolchain1 go.mod
 
 # go get go@patch should use the latest patch release
 go get go@1.22.1
 go get go@patch
 stderr '^go: upgraded go 1.22.1 => 1.22.9$'
 grep 'go 1.22.9' go.mod
-grep 'toolchain go1.99rc1' go.mod
+! grep toolchain go.mod
 
 # go get go@1.24 does NOT find the release candidate
 cp go.mod.orig go.mod
@@ -40,17 +40,22 @@ cp go.mod.orig go.mod
 go get go@1.24rc1
 stderr '^go: upgraded go 1.21 => 1.24rc1$'
 grep 'go 1.24rc1' go.mod
-grep 'toolchain go1.99rc1' go.mod
+! grep toolchain go.mod
 
 # go get go@latest finds the latest Go 1.23
 cp go.mod.orig go.mod
 go get go@latest
 stderr '^go: upgraded go 1.21 => 1.23.9$'
 grep 'go 1.23.9' go.mod
-grep 'toolchain go1.99rc1' go.mod
+! grep toolchain go.mod
 
 # Again, with toolchains.
 
+go get toolchain@go1.99rc1
+stderr '^go: added toolchain go1.99rc1$'
+grep 'go 1.23.9' go.mod
+grep 'toolchain go1.99rc1' go.mod
+
 # go get toolchain should find go1.999testmod.
 go get toolchain
 stderr '^go: upgraded toolchain go1.99rc1 => go1.999testmod$'
index 42c12c1e2ab9803272e3b7f4f55b2c9cf1171d01..d19b93d932c25b3205184ac5cc5a77f9d3851ea3 100644 (file)
@@ -1,5 +1,5 @@
 # This test verifies that 'go get' and 'go mod tidy' switch to a newer toolchain
-# if needed to process newly-reolved imports.
+# if needed to process newly-resolved imports.
 
 env TESTGO_VERSION=go1.21.0
 env TESTGO_VERSION_SWITCH=switch
@@ -46,7 +46,6 @@ go: trying upgrade to example.net/b@v0.1.0
 go: accepting indirect upgrade from go@1.20 to 1.22.0
 go: trying upgrade to example.net/c@v0.1.0
 go: upgraded go 1.20 => 1.22.0
-go: added toolchain go1.22.9
 go: added example.net/b v0.1.0
 go: added example.net/c v0.1.0
 go: added example.net/d v0.1.0
@@ -67,7 +66,6 @@ go: trying upgrade to example.net/c@v0.1.0
 go: trying upgrade to example.net/d@v0.2.0
 go: accepting indirect upgrade from go@1.22.0 to 1.23.0
 go: upgraded go 1.20 => 1.23.0
-go: added toolchain go1.23.9
 go: upgraded example.net/a v0.1.0 => v0.2.0
 go: added example.net/b v0.1.0
 go: added example.net/c v0.1.0
@@ -92,8 +90,6 @@ module example
 
 go 1.22.0
 
-toolchain go1.22.9
-
 require (
        example.net/a v0.1.0
        example.net/b v0.1.0
@@ -117,8 +113,6 @@ module example
 
 go 1.23.0
 
-toolchain go1.23.9
-
 require (
        example.net/a v0.2.0
        example.net/b v0.1.0
index e3f2561f5e367b663cb68e068a6f8967de46105e..e86a9d9cbffe4e5918acbb5342e42e203188b5de 100644 (file)
@@ -131,7 +131,7 @@ cmpenv go.mod go.mod.latest
 
 cp go.mod.117 go.mod
 go mod tidy -go=1.21.0  # lower than $goversion
-cmpenv go.mod go.mod.121toolchain
+cmp go.mod go.mod.121toolchain
 
 
 -- go.mod --
@@ -334,8 +334,6 @@ module example.com/m
 
 go 1.21.0
 
-toolchain $TESTGO_VERSION
-
 require example.net/a v0.1.0
 
 require (
index c771cae0a16e235b62b204b1339a8c8618ac4e73..e96dfbcd8455c3ff7a850e863acd96a437b8e0ef 100644 (file)
@@ -18,9 +18,12 @@ grep 'toolchain go1.22.1' go.mod
 
 go get go@1.22.3
 stderr '^go: upgraded go 1.10 => 1.22.3$'
-stderr '^go: upgraded toolchain go1.22.1 => go1.100.0$'
+! stderr '^go: upgraded toolchain$'
 grep 'go 1.22.3' go.mod
 
+go get toolchain@go1.100.0
+stderr '^go: added toolchain go1.100.0$'
+
 go get go@1.22.3 toolchain@1.22.3
 stderr '^go: removed toolchain go1.100.0$'
 ! grep toolchain go.mod
@@ -65,6 +68,10 @@ stderr '^go: removed toolchain go1.23.9'
 ! stderr ' go 1'
 grep 'go 1.23.5' go.mod
 
+go get toolchain@go1.23.0 go@1.22.0
+go get go@1.24.0
+! grep toolchain go.mod
+
 -- go.mod --
 module m
 go 1.10
index 5a851bb774d98d9145913a763a582c8a893ce439..6548860ac9cc078f1464d858241e7fceac923711 100644 (file)
@@ -1,4 +1,4 @@
-# go get should update the go and toolchain lines in go.work
+# go get should update the go line in go.work
 env TESTGO_VERSION=go1.21
 env TESTGO_VERSION_SWITCH=switch
 env GOTOOLCHAIN=auto
@@ -9,8 +9,8 @@ stderr '^go: rsc.io/needall@v0.0.1 requires go >= 1.23; switching to go1.23.9$'
 stderr '^go: added rsc.io/needall v0.0.1'
 grep 'go 1.23$' go.mod
 grep 'go 1.23$' go.work
-grep 'toolchain go1.23.9' go.mod
-grep 'toolchain go1.23.9' go.work
+! grep toolchain go.mod
+! grep toolchain go.work
 
 -- go.mod.new --
 module m
index b75246272718acef3ab0d79215691e847027f80f..989d6bb792148adac2172dc9307e652e8cd4b652 100644 (file)
@@ -34,7 +34,7 @@ env GOTOOLCHAIN=auto
 go work sync
 stderr '^go: m1_22_1'${/}'go.mod requires go >= 1.22.1; switching to go1.22.9$'
 grep '^go 1.22.1$' go.work
-grep '^toolchain go1.22.9$' go.work
+! grep toolchain go.work
 
 # work sync with newer modules should update go 1.22.1 -> 1.24rc1 and drop toolchain
 go work edit -use=./m1_24_rc0
@@ -42,4 +42,4 @@ go work sync
 stderr '^go: m1_24_rc0'${/}'go.mod requires go >= 1.24rc0; switching to go1.24rc1$'
 cat go.work
 grep '^go 1.24rc0$' go.work
-grep '^toolchain go1.24rc1$' go.work
+! grep toolchain go.work
index bb3db9cf90844bbd39918dffd7add916fd4d3b11..d81e4a4c3ef13e8352abe347accfca44036e5576 100644 (file)
@@ -32,13 +32,13 @@ env GOTOOLCHAIN=auto
 go work use ./m1_22_0
 stderr '^go: m1_22_0'${/}'go.mod requires go >= 1.22.0; switching to go1.22.9$'
 grep '^go 1.22.0$' go.work
-grep '^toolchain go1.22.9$' go.work
+! grep toolchain go.work
 
 # work use with an even newer module should bump go again.
 go work use ./m1_22_1
-! stderr switching
+stderr '^go: m1_22_1'${/}'go.mod requires go >= 1.22.1; switching to go1.22.9$'
 grep '^go 1.22.1$' go.work
-grep '^toolchain go1.22.9$' go.work  # unchanged
+! grep toolchain go.work
 
 # work use with an even newer module should bump go and toolchain again.
 env GOTOOLCHAIN=go1.22.9
@@ -48,4 +48,4 @@ env GOTOOLCHAIN=auto
 go work use ./m1_24_rc0
 stderr '^go: m1_24_rc0'${/}'go.mod requires go >= 1.24rc0; switching to go1.24rc1$'
 grep '^go 1.24rc0$' go.work
-grep '^toolchain go1.24rc1$' go.work
+! grep 'toolchain' go.work