]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: add loaderstate to Switcher
authorIan Alexander <jitsu@google.com>
Thu, 16 Oct 2025 21:43:58 +0000 (17:43 -0400)
committerIan Alexander <jitsu@google.com>
Mon, 20 Oct 2025 19:55:20 +0000 (12:55 -0700)
Temporarily add modload.State field to the Switcher implementation.
Note that we cannot modify the gover.Switcher interface because doing
so creates an import cycle.

This commit is part of the overall effort to eliminate global
modloader state.

Change-Id: I20dba76328aa3d0df58caff75b174522bf9df9d5
Reviewed-on: https://go-review.googlesource.com/c/go/+/712703
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Matloob <matloob@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
src/cmd/go/internal/modcmd/download.go
src/cmd/go/internal/modcmd/tidy.go
src/cmd/go/internal/modget/get.go
src/cmd/go/internal/toolchain/select.go
src/cmd/go/internal/toolchain/switch.go
src/cmd/go/internal/workcmd/use.go

index e5e0e927b04ebef55b87735d12fac0183083447a..0d223b382692f645c9deca40ac931b88395ef379 100644 (file)
@@ -211,7 +211,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
        // toolchain version) or only one module (as is used by the Go Module Proxy).
 
        if infosErr != nil {
-               var sw toolchain.Switcher
+               sw := toolchain.NewSwitcher(modload.LoaderState)
                sw.Error(infosErr)
                if sw.NeedSwitch() {
                        sw.Switch(ctx)
@@ -292,7 +292,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
        // which may include dependencies that are normally pruned out
        // of the individual modules in the workspace.
        if haveExplicitArgs || modload.WorkFilePath(modload.LoaderState) != "" {
-               var sw toolchain.Switcher
+               sw := toolchain.NewSwitcher(modload.LoaderState)
                // Add errors to the Switcher in deterministic order so that they will be
                // logged deterministically.
                for _, m := range mods {
index c693bd52a38af966660f3a3f08858720b45cd5b4..8a8b4e34c0cf7169b15d3f11b9c307dad7e86384 100644 (file)
@@ -141,6 +141,6 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
                LoadTests:                true,
                AllowErrors:              tidyE,
                SilenceMissingStdImports: true,
-               Switcher:                 new(toolchain.Switcher),
+               Switcher:                 toolchain.NewSwitcher(modload.LoaderState),
        }, "all")
 }
index b26406ee1d0fa20377febf880eeb86479846568e..8972e4152e077986411dc2b9ec6bf9a6a5030e64 100644 (file)
@@ -1260,7 +1260,7 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack
                LoadTests:                *getT,
                AssumeRootsImported:      true, // After 'go get foo', imports of foo should build.
                SilencePackageErrors:     true, // May be fixed by subsequent upgrades or downgrades.
-               Switcher:                 new(toolchain.Switcher),
+               Switcher:                 toolchain.NewSwitcher(modload.LoaderState),
        }
 
        opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error {
@@ -1346,7 +1346,7 @@ func (r *resolver) resolveQueries(ctx context.Context, queries []*query) (change
 
                // If we found modules that were too new, find the max of the required versions
                // and then try to switch to a newer toolchain.
-               var sw toolchain.Switcher
+               sw := toolchain.NewSwitcher(modload.LoaderState)
                for _, q := range queries {
                        for _, cs := range q.candidates {
                                sw.Error(cs.err)
index 8aa84e885f58bfc02814b57a6f270b7237fc2346..8a7e51c1437557bad465a6feefa07c99eebc1f46 100644 (file)
@@ -283,7 +283,7 @@ func Select() {
        }
 
        counterSelectExec.Inc()
-       Exec(gotoolchain)
+       Exec(modload.LoaderState, gotoolchain)
 }
 
 var counterSelectExec = counter.New("go/toolchain/select-exec")
@@ -300,7 +300,7 @@ var TestVersionSwitch string
 // If $GOTOOLCHAIN is set to path or min+path, Exec only considers the PATH
 // as a source of Go toolchains. Otherwise Exec tries the PATH but then downloads
 // a toolchain if necessary.
-func Exec(gotoolchain string) {
+func Exec(s *modload.State, gotoolchain string) {
        log.SetPrefix("go: ")
 
        writeBits = sysWriteBits()
@@ -352,10 +352,10 @@ func Exec(gotoolchain string) {
        }
 
        // Set up modules without an explicit go.mod, to download distribution.
-       modload.LoaderState.Reset()
-       modload.LoaderState.ForceUseModules = true
-       modload.LoaderState.RootMode = modload.NoRoot
-       modload.Init(modload.LoaderState)
+       s.Reset()
+       s.ForceUseModules = true
+       s.RootMode = modload.NoRoot
+       modload.Init(s)
 
        // Download and unpack toolchain module into module cache.
        // Note that multiple go commands might be doing this at the same time,
@@ -709,7 +709,7 @@ func maybeSwitchForGoInstallVersion(minVers string) {
        if errors.Is(err, gover.ErrTooNew) {
                // Run early switch, same one go install or go run would eventually do,
                // if it understood all the command-line flags.
-               var s Switcher
+               s := NewSwitcher(modload.LoaderState)
                s.Error(err)
                if s.TooNew != nil && gover.Compare(s.TooNew.GoVersion, minVers) > 0 {
                        SwitchOrFatal(ctx, err)
index 37c1bcdcbec6567734a033622ebe5589d93e54ac..9fedea3abbf4b77fc1ad267d0eeea76f4b71e833 100644 (file)
@@ -16,6 +16,7 @@ import (
        "cmd/go/internal/cfg"
        "cmd/go/internal/gover"
        "cmd/go/internal/modfetch"
+       "cmd/go/internal/modload"
        "cmd/internal/telemetry/counter"
 )
 
@@ -31,8 +32,15 @@ import (
 //
 // See https://go.dev/doc/toolchain#switch.
 type Switcher struct {
-       TooNew *gover.TooNewError // max go requirement observed
-       Errors []error            // errors collected so far
+       TooNew      *gover.TooNewError // max go requirement observed
+       Errors      []error            // errors collected so far
+       loaderstate *modload.State     // temporarily here while we eliminate global module loader state
+}
+
+func NewSwitcher(s *modload.State) *Switcher {
+       sw := new(Switcher)
+       sw.loaderstate = s
+       return sw
 }
 
 // Error reports the error to the Switcher,
@@ -100,7 +108,7 @@ func (s *Switcher) Switch(ctx context.Context) {
 
        fmt.Fprintf(os.Stderr, "go: %v requires go >= %v; switching to %v\n", s.TooNew.What, s.TooNew.GoVersion, tv)
        counterSwitchExec.Inc()
-       Exec(tv)
+       Exec(s.loaderstate, tv)
        panic("unreachable")
 }
 
@@ -109,7 +117,7 @@ var counterSwitchExec = counter.New("go/toolchain/switch-exec")
 // SwitchOrFatal attempts a toolchain switch based on the information in err
 // and otherwise falls back to base.Fatal(err).
 func SwitchOrFatal(ctx context.Context, err error) {
-       var s Switcher
+       s := NewSwitcher(modload.LoaderState)
        s.Error(err)
        s.Switch(ctx)
        base.Exit()
index ca8de22cca884f70c83e981505d54445d726153c..367e8fe379fafb8a67492214938a419076f21ffc 100644 (file)
@@ -94,7 +94,7 @@ func workUse(ctx context.Context, gowork string, wf *modfile.WorkFile, args []st
        // all entries for the absolute path should be removed.
        keepDirs := make(map[string]string)
 
-       var sw toolchain.Switcher
+       sw := toolchain.NewSwitcher(modload.LoaderState)
 
        // lookDir updates the entry in keepDirs for the directory dir,
        // which is either absolute or relative to the current working directory