]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: inject State parameter into `run.runRun`
authorIan Alexander <jitsu@google.com>
Thu, 21 Aug 2025 01:59:08 +0000 (21:59 -0400)
committerIan Alexander <jitsu@google.com>
Wed, 15 Oct 2025 15:59:02 +0000 (08:59 -0700)
This command modifies the call tree starting at `run.runRun` to inject
a `State` parameter to every function that is currently using the
global `modload.LoaderState` variable.  By explicilty passing a
`State` parameter, we can begin to eliminate the usage of the global
`modload.LoaderState`.

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

[git-generate]
cd src/cmd/go/internal/run
rf 'inject modload.LoaderState runRun'
cd ..
./rf-cleanup.zsh

Change-Id: I337323c087ed4e43af28973fad27152791eefbc2
Reviewed-on: https://go-review.googlesource.com/c/go/+/698063
TryBot-Bypass: Ian Alexander <jitsu@google.com>
Reviewed-by: Michael Matloob <matloob@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
49 files changed:
src/cmd/go/internal/bug/bug.go
src/cmd/go/internal/clean/clean.go
src/cmd/go/internal/envcmd/env.go
src/cmd/go/internal/fmtcmd/fmt.go
src/cmd/go/internal/generate/generate.go
src/cmd/go/internal/list/list.go
src/cmd/go/internal/load/flag.go
src/cmd/go/internal/load/godebug.go
src/cmd/go/internal/load/pkg.go
src/cmd/go/internal/load/search.go
src/cmd/go/internal/load/test.go
src/cmd/go/internal/modcmd/download.go
src/cmd/go/internal/modcmd/graph.go
src/cmd/go/internal/modcmd/tidy.go
src/cmd/go/internal/modcmd/vendor.go
src/cmd/go/internal/modcmd/verify.go
src/cmd/go/internal/modcmd/why.go
src/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
src/cmd/go/internal/modget/get.go
src/cmd/go/internal/modget/query.go
src/cmd/go/internal/modload/build.go
src/cmd/go/internal/modload/buildlist.go
src/cmd/go/internal/modload/edit.go
src/cmd/go/internal/modload/import.go
src/cmd/go/internal/modload/import_test.go
src/cmd/go/internal/modload/init.go
src/cmd/go/internal/modload/list.go
src/cmd/go/internal/modload/load.go
src/cmd/go/internal/modload/modfile.go
src/cmd/go/internal/modload/mvs.go
src/cmd/go/internal/modload/query.go
src/cmd/go/internal/modload/query_test.go
src/cmd/go/internal/modload/search.go
src/cmd/go/internal/modload/vendor.go
src/cmd/go/internal/run/run.go
src/cmd/go/internal/telemetrystats/telemetrystats.go
src/cmd/go/internal/test/test.go
src/cmd/go/internal/tool/tool.go
src/cmd/go/internal/toolchain/select.go
src/cmd/go/internal/vet/vet.go
src/cmd/go/internal/work/action.go
src/cmd/go/internal/work/build.go
src/cmd/go/internal/work/exec.go
src/cmd/go/internal/work/init.go
src/cmd/go/internal/workcmd/edit.go
src/cmd/go/internal/workcmd/init.go
src/cmd/go/internal/workcmd/sync.go
src/cmd/go/internal/workcmd/use.go
src/cmd/go/internal/workcmd/vendor.go

index 4ff45d2d888c9671e366ef9781a57543d8aae96f..4e9ae1e9b499cac8e3f6168876c09da78c6e1856 100644 (file)
@@ -21,6 +21,7 @@ import (
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
        "cmd/go/internal/envcmd"
+       "cmd/go/internal/modload"
        "cmd/go/internal/web"
        "cmd/go/internal/work"
 )
@@ -44,7 +45,7 @@ func runBug(ctx context.Context, cmd *base.Command, args []string) {
        if len(args) > 0 {
                base.Fatalf("go: bug takes no arguments")
        }
-       work.BuildInit()
+       work.BuildInit(modload.LoaderState)
 
        var buf strings.Builder
        buf.WriteString(bugHeader)
index c6f311e0263af8b568701cae8b934e9d2c61eb96..1c05977de554f8eed298f3032353108c983398c3 100644 (file)
@@ -120,7 +120,7 @@ func init() {
 }
 
 func runClean(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
        if len(args) > 0 {
                cacheFlag := ""
                switch {
@@ -142,13 +142,13 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
        // either the flags and arguments explicitly imply a package,
        // or no other target (such as a cache) was requested to be cleaned.
        cleanPkg := len(args) > 0 || cleanI || cleanR
-       if (!modload.Enabled() || modload.HasModRoot()) &&
+       if (!modload.Enabled(modload.LoaderState) || modload.HasModRoot(modload.LoaderState)) &&
                !cleanCache && !cleanModcache && !cleanTestcache && !cleanFuzzcache {
                cleanPkg = true
        }
 
        if cleanPkg {
-               for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) {
+               for _, pkg := range load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{}, args) {
                        clean(pkg)
                }
        }
index 6ad6954dd521255ae4dde2a70d1a6553ba013850..13708ae170c1d84d4085134718d9275bb23af99f 100644 (file)
@@ -191,14 +191,14 @@ func findEnv(env []cfg.EnvVar, name string) string {
 // ExtraEnvVars returns environment variables that should not leak into child processes.
 func ExtraEnvVars() []cfg.EnvVar {
        gomod := ""
-       modload.Init()
-       if modload.HasModRoot() {
+       modload.Init(modload.LoaderState)
+       if modload.HasModRoot(modload.LoaderState) {
                gomod = modload.ModFilePath()
-       } else if modload.Enabled() {
+       } else if modload.Enabled(modload.LoaderState) {
                gomod = os.DevNull
        }
-       modload.InitWorkfile()
-       gowork := modload.WorkFilePath()
+       modload.InitWorkfile(modload.LoaderState)
+       gowork := modload.WorkFilePath(modload.LoaderState)
        // As a special case, if a user set off explicitly, report that in GOWORK.
        if cfg.Getenv("GOWORK") == "off" {
                gowork = "off"
@@ -336,7 +336,7 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
                }
        }
        if needCostly {
-               work.BuildInit()
+               work.BuildInit(modload.LoaderState)
                env = append(env, ExtraEnvVarsCostly()...)
        }
 
index 83fba9661a66fcd3f51908c48c0b8a9e9476ed53..a42e7753050356fbe46659b2cceefb8275740d43 100644 (file)
@@ -59,8 +59,8 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) {
        baseGofmtArgs := len(gofmtArgs)
        baseGofmtArgLen := gofmtArgLen
 
-       for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) {
-               if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
+       for _, pkg := range load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{}, args) {
+               if modload.Enabled(modload.LoaderState) && pkg.Module != nil && !pkg.Module.Main {
                        if !printed {
                                fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n")
                                printed = true
@@ -70,7 +70,7 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) {
                if pkg.Error != nil {
                        if _, ok := errors.AsType[*load.NoGoError](pkg.Error); ok {
                                // Skip this error, as we will format all files regardless.
-                       } else if  _, ok := errors.AsType[*load.EmbedError](pkg.Error); ok && len(pkg.InternalAllGoFiles()) > 0 {
+                       } else if _, ok := errors.AsType[*load.EmbedError](pkg.Error); ok && len(pkg.InternalAllGoFiles()) > 0 {
                                // Skip this error, as we will format all files regardless.
                        } else {
                                base.Errorf("%v", pkg.Error)
index 0f4b4a972e9107617cc3412e5a169f3f09fbc075..4250916b8d09d67106af406ea4d1017ba2abccce 100644 (file)
@@ -182,7 +182,7 @@ func init() {
 }
 
 func runGenerate(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
 
        if generateRunFlag != "" {
                var err error
@@ -204,8 +204,8 @@ func runGenerate(ctx context.Context, cmd *base.Command, args []string) {
        // Even if the arguments are .go files, this loop suffices.
        printed := false
        pkgOpts := load.PackageOpts{IgnoreImports: true}
-       for _, pkg := range load.PackagesAndErrors(ctx, pkgOpts, args) {
-               if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
+       for _, pkg := range load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, args) {
+               if modload.Enabled(modload.LoaderState) && pkg.Module != nil && !pkg.Module.Main {
                        if !printed {
                                fmt.Fprintf(os.Stderr, "go: not generating in packages in dependency modules\n")
                                printed = true
index bee7dc8053ee6f8b140d7ddef869863d7575f49f..0bf86ae004a26e53f769623cea87e9d43eace195 100644 (file)
@@ -419,7 +419,7 @@ func (v *jsonFlag) needAny(fields ...string) bool {
 var nl = []byte{'\n'}
 
 func runList(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
 
        if *listFmt != "" && listJson {
                base.Fatalf("go list -f cannot be used with -json")
@@ -427,11 +427,11 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
        if *listReuse != "" && !*listM {
                base.Fatalf("go list -reuse cannot be used without -m")
        }
-       if *listReuse != "" && modload.HasModRoot() {
+       if *listReuse != "" && modload.HasModRoot(modload.LoaderState) {
                base.Fatalf("go list -reuse cannot be used inside a module")
        }
 
-       work.BuildInit()
+       work.BuildInit(modload.LoaderState)
        out := newTrackingWriter(os.Stdout)
        defer out.w.Flush()
 
@@ -496,12 +496,12 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                }
        }
 
-       modload.Init()
+       modload.Init(modload.LoaderState)
        if *listRetracted {
                if cfg.BuildMod == "vendor" {
                        base.Fatalf("go list -retracted cannot be used when vendoring is enabled")
                }
-               if !modload.Enabled() {
+               if !modload.Enabled(modload.LoaderState) {
                        base.Fatalf("go list -retracted can only be used in module-aware mode")
                }
        }
@@ -525,11 +525,11 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                        base.Fatalf("go list -test cannot be used with -m")
                }
 
-               if modload.Init(); !modload.Enabled() {
+               if modload.Init(modload.LoaderState); !modload.Enabled(modload.LoaderState) {
                        base.Fatalf("go: list -m cannot be used with GO111MODULE=off")
                }
 
-               modload.LoadModFile(ctx) // Sets cfg.BuildMod as a side-effect.
+               modload.LoadModFile(modload.LoaderState, ctx) // Sets cfg.BuildMod as a side-effect.
                if cfg.BuildMod == "vendor" {
                        const actionDisabledFormat = "go: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
 
@@ -613,7 +613,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                SuppressBuildInfo:  !*listExport && !listJsonFields.needAny("Stale", "StaleReason"),
                SuppressEmbedFiles: !*listExport && !listJsonFields.needAny("EmbedFiles", "TestEmbedFiles", "XTestEmbedFiles"),
        }
-       pkgs := load.PackagesAndErrors(ctx, pkgOpts, args)
+       pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, args)
        if !*listE {
                w := 0
                for _, pkg := range pkgs {
@@ -727,7 +727,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                b.NeedExport = *listExport
                b.NeedCompiledGoFiles = *listCompiled
                if cfg.BuildCover {
-                       load.PrepareForCoverageBuild(pkgs)
+                       load.PrepareForCoverageBuild(modload.LoaderState, pkgs)
                }
                a := &work.Action{}
                // TODO: Use pkgsFilter?
index 55bdab013505abc21d547e39bcf8e944a22099f4..86a922bc103a82d879b0e8733a191deaac499534 100644 (file)
@@ -6,6 +6,7 @@ package load
 
 import (
        "cmd/go/internal/base"
+       "cmd/go/internal/modload"
        "cmd/internal/quoted"
        "fmt"
        "strings"
@@ -63,7 +64,7 @@ func (f *PerPackageFlag) set(v, cwd string) error {
                        return fmt.Errorf("parameter may not start with quote character %c", v[0])
                }
                pattern := strings.TrimSpace(v[:i])
-               match = MatchPackage(pattern, cwd)
+               match = MatchPackage(modload.LoaderState, pattern, cwd)
                v = v[i+1:]
        }
        flags, err := quoted.Split(v)
index c795d42f117f0e7f9b7e9e924ea1a9f3237228fd..817cc4faebf7b477cd07d5506a4aafa41e4d02a9 100644 (file)
@@ -45,12 +45,12 @@ func ParseGoDebug(text string) (key, value string, err error) {
 // defaultGODEBUG returns the default GODEBUG setting for the main package p.
 // When building a test binary, directives, testDirectives, and xtestDirectives
 // list additional directives from the package under test.
-func defaultGODEBUG(p *Package, directives, testDirectives, xtestDirectives []build.Directive) string {
+func defaultGODEBUG(loaderstate *modload.State, p *Package, directives, testDirectives, xtestDirectives []build.Directive) string {
        if p.Name != "main" {
                return ""
        }
-       goVersion := modload.LoaderState.MainModules.GoVersion()
-       if modload.LoaderState.RootMode == modload.NoRoot && p.Module != nil {
+       goVersion := loaderstate.MainModules.GoVersion(loaderstate)
+       if loaderstate.RootMode == modload.NoRoot && p.Module != nil {
                // This is go install pkg@version or go run pkg@version.
                // Use the Go version from the package.
                // If there isn't one, then assume Go 1.20,
@@ -73,7 +73,7 @@ func defaultGODEBUG(p *Package, directives, testDirectives, xtestDirectives []bu
        }
 
        // Add directives from main module go.mod.
-       for _, g := range modload.LoaderState.MainModules.Godebugs() {
+       for _, g := range loaderstate.MainModules.Godebugs(loaderstate) {
                if m == nil {
                        m = make(map[string]string)
                }
index a894affc8440668e15b7d303562f3505aef71518..cfaece2072dbb976bcfa94188cb437ff2dfeee0f 100644 (file)
@@ -686,8 +686,8 @@ const (
 )
 
 // LoadPackage does Load import, but without a parent package load context
-func LoadPackage(ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
-       p, err := loadImport(ctx, opts, nil, path, srcDir, nil, stk, importPos, mode)
+func LoadPackage(loaderstate *modload.State, ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
+       p, err := loadImport(loaderstate, ctx, opts, nil, path, srcDir, nil, stk, importPos, mode)
        if err != nil {
                base.Fatalf("internal error: loadImport of %q with nil parent returned an error", path)
        }
@@ -703,7 +703,7 @@ func LoadPackage(ctx context.Context, opts PackageOpts, path, srcDir string, stk
 // The returned PackageError, if any, describes why parent is not allowed
 // to import the named package, with the error referring to importPos.
 // The PackageError can only be non-nil when parent is not nil.
-func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
+func loadImport(loaderstate *modload.State, ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
        ctx, span := trace.StartSpan(ctx, "modload.loadImport "+path)
        defer span.Done()
 
@@ -718,9 +718,9 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi
                parentRoot = parent.Root
                parentIsStd = parent.Standard
        }
-       bp, loaded, err := loadPackageData(ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode)
+       bp, loaded, err := loadPackageData(loaderstate, ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode)
        if loaded && pre != nil && !opts.IgnoreImports {
-               pre.preloadImports(ctx, opts, bp.Imports, bp)
+               pre.preloadImports(loaderstate, ctx, opts, bp.Imports, bp)
        }
        if bp == nil {
                p := &Package{
@@ -771,7 +771,7 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi
                // Load package.
                // loadPackageData may return bp != nil even if an error occurs,
                // in order to return partial information.
-               p.load(ctx, opts, path, stk, importPos, bp, err)
+               p.load(loaderstate, ctx, opts, path, stk, importPos, bp, err)
 
                if !cfg.ModulesEnabled && path != cleanImport(path) {
                        p.Error = &PackageError{
@@ -784,7 +784,7 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi
        }
 
        // Checked on every import because the rules depend on the code doing the importing.
-       if perr := disallowInternal(ctx, srcDir, parent, parentPath, p, stk); perr != nil {
+       if perr := disallowInternal(loaderstate, ctx, srcDir, parent, parentPath, p, stk); perr != nil {
                perr.setPos(importPos)
                return p, perr
        }
@@ -838,7 +838,7 @@ func extractFirstImport(importPos []token.Position) *token.Position {
 //
 // loadPackageData returns a boolean, loaded, which is true if this is the
 // first time the package was loaded. Callers may preload imports in this case.
-func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
+func loadPackageData(loaderstate *modload.State, ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
        ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path)
        defer span.Done()
 
@@ -883,7 +883,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
                        r.path = newPath
                        r.dir = dir
                } else if cfg.ModulesEnabled {
-                       r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
+                       r.dir, r.path, r.err = modload.Lookup(loaderstate, parentPath, parentIsStd, path)
                } else if build.IsLocalImport(path) {
                        r.dir = filepath.Join(parentDir, path)
                        r.path = dirToImportPath(r.dir)
@@ -892,7 +892,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
                        // find out the key to use in packageCache without the
                        // overhead of repeated calls to buildContext.Import.
                        // The code is also needed in a few other places anyway.
-                       r.path = resolveImportPath(path, parentPath, parentDir, parentRoot, parentIsStd)
+                       r.path = resolveImportPath(loaderstate, path, parentPath, parentDir, parentRoot, parentIsStd)
                } else if mode&ResolveModule != 0 {
                        r.path = moduleImportPath(path, parentPath, parentDir, parentRoot)
                }
@@ -921,7 +921,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
                        } else {
                                buildContext.GOPATH = "" // Clear GOPATH so packages are imported as pure module packages
                        }
-                       modroot := modload.PackageModRoot(ctx, r.path)
+                       modroot := modload.PackageModRoot(loaderstate, ctx, r.path)
                        if modroot == "" && str.HasPathPrefix(r.dir, cfg.GOROOTsrc) {
                                modroot = cfg.GOROOTsrc
                                gorootSrcCmd := filepath.Join(cfg.GOROOTsrc, "cmd")
@@ -942,7 +942,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
                        if cfg.ModulesEnabled {
                                // Override data.p.Root, since ImportDir sets it to $GOPATH, if
                                // the module is inside $GOPATH/src.
-                               if info := modload.PackageModuleInfo(ctx, path); info != nil {
+                               if info := modload.PackageModuleInfo(loaderstate, ctx, path); info != nil {
                                        data.p.Root = info.Dir
                                }
                        }
@@ -989,7 +989,7 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
                        if cfg.GOBIN != "" {
                                data.p.BinDir = cfg.GOBIN
                        } else if cfg.ModulesEnabled {
-                               data.p.BinDir = modload.BinDir()
+                               data.p.BinDir = modload.BinDir(loaderstate)
                        }
                }
 
@@ -1068,7 +1068,7 @@ func newPreload() *preload {
 // preloadMatches loads data for package paths matched by patterns.
 // When preloadMatches returns, some packages may not be loaded yet, but
 // loadPackageData and loadImport are always safe to call.
-func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matches []*search.Match) {
+func (pre *preload) preloadMatches(loaderstate *modload.State, ctx context.Context, opts PackageOpts, matches []*search.Match) {
        for _, m := range matches {
                for _, pkg := range m.Pkgs {
                        select {
@@ -1077,10 +1077,10 @@ func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matche
                        case pre.sema <- struct{}{}:
                                go func(pkg string) {
                                        mode := 0 // don't use vendoring or module import resolution
-                                       bp, loaded, err := loadPackageData(ctx, pkg, "", base.Cwd(), "", false, mode)
+                                       bp, loaded, err := loadPackageData(loaderstate, ctx, pkg, "", base.Cwd(), "", false, mode)
                                        <-pre.sema
                                        if bp != nil && loaded && err == nil && !opts.IgnoreImports {
-                                               pre.preloadImports(ctx, opts, bp.Imports, bp)
+                                               pre.preloadImports(loaderstate, ctx, opts, bp.Imports, bp)
                                        }
                                }(pkg)
                        }
@@ -1091,7 +1091,7 @@ func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matche
 // preloadImports queues a list of imports for preloading.
 // When preloadImports returns, some packages may not be loaded yet,
 // but loadPackageData and loadImport are always safe to call.
-func (pre *preload) preloadImports(ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) {
+func (pre *preload) preloadImports(loaderstate *modload.State, ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) {
        parentIsStd := parent.Goroot && parent.ImportPath != "" && search.IsStandardImportPath(parent.ImportPath)
        for _, path := range imports {
                if path == "C" || path == "unsafe" {
@@ -1102,10 +1102,10 @@ func (pre *preload) preloadImports(ctx context.Context, opts PackageOpts, import
                        return
                case pre.sema <- struct{}{}:
                        go func(path string) {
-                               bp, loaded, err := loadPackageData(ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport)
+                               bp, loaded, err := loadPackageData(loaderstate, ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport)
                                <-pre.sema
                                if bp != nil && loaded && err == nil && !opts.IgnoreImports {
-                                       pre.preloadImports(ctx, opts, bp.Imports, bp)
+                                       pre.preloadImports(loaderstate, ctx, opts, bp.Imports, bp)
                                }
                        }(path)
                }
@@ -1160,12 +1160,12 @@ func ResolveImportPath(parent *Package, path string) (found string) {
                parentRoot = parent.Root
                parentIsStd = parent.Standard
        }
-       return resolveImportPath(path, parentPath, parentDir, parentRoot, parentIsStd)
+       return resolveImportPath(modload.LoaderState, path, parentPath, parentDir, parentRoot, parentIsStd)
 }
 
-func resolveImportPath(path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) {
+func resolveImportPath(loaderstate *modload.State, path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) {
        if cfg.ModulesEnabled {
-               if _, p, e := modload.Lookup(parentPath, parentIsStd, path); e == nil {
+               if _, p, e := modload.Lookup(loaderstate, parentPath, parentIsStd, path); e == nil {
                        return p
                }
                return path
@@ -1463,7 +1463,7 @@ func reusePackage(p *Package, stk *ImportStack) *Package {
 // is allowed to import p.
 // If the import is allowed, disallowInternal returns the original package p.
 // If not, it returns a new package containing just an appropriate error.
-func disallowInternal(ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *PackageError {
+func disallowInternal(loaderstate *modload.State, ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *PackageError {
        // golang.org/s/go14internal:
        // An import of a path containing the element “internal”
        // is disallowed if the importing code is outside the tree
@@ -1552,7 +1552,7 @@ func disallowInternal(ctx context.Context, srcDir string, importer *Package, imp
                        // directory containing them.
                        // If the directory is outside the main modules, this will resolve to ".",
                        // which is not a prefix of any valid module.
-                       importerPath, _ = modload.LoaderState.MainModules.DirImportPath(ctx, importer.Dir)
+                       importerPath, _ = loaderstate.MainModules.DirImportPath(loaderstate, ctx, importer.Dir)
                }
                parentOfInternal := p.ImportPath[:i]
                if str.HasPathPrefix(importerPath, parentOfInternal) {
@@ -1771,7 +1771,7 @@ func (p *Package) DefaultExecName() string {
 // load populates p using information from bp, err, which should
 // be the result of calling build.Context.Import.
 // stk contains the import stack, not including path itself.
-func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {
+func (p *Package) load(loaderstate *modload.State, ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {
        p.copyBuild(opts, bp)
 
        // The localPrefix is the path we interpret ./ imports relative to,
@@ -1835,7 +1835,7 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *
                        elem = full
                }
                if p.Internal.Build.BinDir == "" && cfg.ModulesEnabled {
-                       p.Internal.Build.BinDir = modload.BinDir()
+                       p.Internal.Build.BinDir = modload.BinDir(loaderstate)
                }
                if p.Internal.Build.BinDir != "" {
                        // Install to GOBIN or bin of GOPATH entry.
@@ -1973,9 +1973,9 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *
                pkgPath = "command-line-arguments"
        }
        if cfg.ModulesEnabled {
-               p.Module = modload.PackageModuleInfo(ctx, pkgPath)
+               p.Module = modload.PackageModuleInfo(loaderstate, ctx, pkgPath)
        }
-       p.DefaultGODEBUG = defaultGODEBUG(p, nil, nil, nil)
+       p.DefaultGODEBUG = defaultGODEBUG(loaderstate, p, nil, nil, nil)
 
        if !opts.SuppressEmbedFiles {
                p.EmbedFiles, p.Internal.Embed, err = resolveEmbed(p.Dir, p.EmbedPatterns)
@@ -2026,7 +2026,7 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *
                if path == "C" {
                        continue
                }
-               p1, err := loadImport(ctx, opts, nil, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport)
+               p1, err := loadImport(loaderstate, ctx, opts, nil, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport)
                if err != nil && p.Error == nil {
                        p.Error = err
                        p.Incomplete = true
@@ -2813,7 +2813,7 @@ func TestPackageList(ctx context.Context, opts PackageOpts, roots []*Package) []
        }
        walkTest := func(root *Package, path string) {
                var stk ImportStack
-               p1, err := loadImport(ctx, opts, nil, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport)
+               p1, err := loadImport(modload.LoaderState, ctx, opts, nil, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport)
                if err != nil && root.Error == nil {
                        // Assign error importing the package to the importer.
                        root.Error = err
@@ -2840,16 +2840,16 @@ func TestPackageList(ctx context.Context, opts PackageOpts, roots []*Package) []
 // dependencies (like sync/atomic for coverage).
 // TODO(jayconrod): delete this function and set flags automatically
 // in LoadImport instead.
-func LoadImportWithFlags(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
-       p, err := loadImport(context.TODO(), PackageOpts{}, nil, path, srcDir, parent, stk, importPos, mode)
+func LoadImportWithFlags(loaderstate *modload.State, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
+       p, err := loadImport(loaderstate, context.TODO(), PackageOpts{}, nil, path, srcDir, parent, stk, importPos, mode)
        setToolFlags(p)
        return p, err
 }
 
 // LoadPackageWithFlags is the same as LoadImportWithFlags but without a parent.
 // It's then guaranteed to not return an error
-func LoadPackageWithFlags(path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
-       p := LoadPackage(context.TODO(), PackageOpts{}, path, srcDir, stk, importPos, mode)
+func LoadPackageWithFlags(loaderstate *modload.State, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
+       p := LoadPackage(loaderstate, context.TODO(), PackageOpts{}, path, srcDir, stk, importPos, mode)
        setToolFlags(p)
        return p
 }
@@ -2899,7 +2899,7 @@ type PackageOpts struct {
 //
 // To obtain a flat list of packages, use PackageList.
 // To report errors loading packages, use ReportPackageErrors.
-func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) []*Package {
+func PackagesAndErrors(loaderstate *modload.State, ctx context.Context, opts PackageOpts, patterns []string) []*Package {
        ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors")
        defer span.Done()
 
@@ -2911,7 +2911,7 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string)
                        // We need to test whether the path is an actual Go file and not a
                        // package path or pattern ending in '.go' (see golang.org/issue/34653).
                        if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
-                               pkgs := []*Package{GoFilesPackage(ctx, opts, patterns)}
+                               pkgs := []*Package{GoFilesPackage(loaderstate, ctx, opts, patterns)}
                                setPGOProfilePath(pkgs)
                                return pkgs
                        }
@@ -2919,13 +2919,13 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string)
        }
 
        var matches []*search.Match
-       if modload.Init(); cfg.ModulesEnabled {
+       if modload.Init(loaderstate); cfg.ModulesEnabled {
                modOpts := modload.PackageOpts{
                        ResolveMissingImports: true,
                        LoadTests:             opts.ModResolveTests,
                        SilencePackageErrors:  true,
                }
-               matches, _ = modload.LoadPackages(ctx, modOpts, patterns...)
+               matches, _ = modload.LoadPackages(loaderstate, ctx, modOpts, patterns...)
        } else {
                matches = search.ImportPaths(patterns)
        }
@@ -2938,7 +2938,7 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string)
 
        pre := newPreload()
        defer pre.flush()
-       pre.preloadMatches(ctx, opts, matches)
+       pre.preloadMatches(loaderstate, ctx, opts, matches)
 
        for _, m := range matches {
                for _, pkg := range m.Pkgs {
@@ -2952,7 +2952,7 @@ func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string)
                                // a literal and also a non-literal pattern.
                                mode |= cmdlinePkgLiteral
                        }
-                       p, perr := loadImport(ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, mode)
+                       p, perr := loadImport(loaderstate, ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, mode)
                        if perr != nil {
                                base.Fatalf("internal error: loadImport of %q with nil parent returned an error", pkg)
                        }
@@ -3243,8 +3243,8 @@ func setToolFlags(pkgs ...*Package) {
 // GoFilesPackage creates a package for building a collection of Go files
 // (typically named on the command line). The target is named p.a for
 // package p or named after the first Go file for package main.
-func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Package {
-       modload.Init()
+func GoFilesPackage(loaderstate *modload.State, ctx context.Context, opts PackageOpts, gofiles []string) *Package {
+       modload.Init(loaderstate)
 
        for _, f := range gofiles {
                if !strings.HasSuffix(f, ".go") {
@@ -3289,7 +3289,7 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa
        ctxt.ReadDir = func(string) ([]fs.FileInfo, error) { return dirent, nil }
 
        if cfg.ModulesEnabled {
-               modload.ImportFromFiles(ctx, gofiles)
+               modload.ImportFromFiles(loaderstate, ctx, gofiles)
        }
 
        var err error
@@ -3305,7 +3305,7 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa
        pkg := new(Package)
        pkg.Internal.Local = true
        pkg.Internal.CmdlineFiles = true
-       pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err)
+       pkg.load(loaderstate, ctx, opts, "command-line-arguments", &stk, nil, bp, err)
        if !cfg.ModulesEnabled {
                pkg.Internal.LocalPrefix = dirToImportPath(dir)
        }
@@ -3319,7 +3319,7 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa
                if cfg.GOBIN != "" {
                        pkg.Target = filepath.Join(cfg.GOBIN, exe)
                } else if cfg.ModulesEnabled {
-                       pkg.Target = filepath.Join(modload.BinDir(), exe)
+                       pkg.Target = filepath.Join(modload.BinDir(loaderstate), exe)
                }
        }
 
@@ -3347,11 +3347,11 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa
 // module, but its go.mod file (if it has one) must not contain directives that
 // would cause it to be interpreted differently if it were the main module
 // (replace, exclude).
-func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) {
-       if !modload.LoaderState.ForceUseModules {
+func PackagesAndErrorsOutsideModule(loaderstate *modload.State, ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) {
+       if !loaderstate.ForceUseModules {
                panic("modload.ForceUseModules must be true")
        }
-       if modload.LoaderState.RootMode != modload.NoRoot {
+       if loaderstate.RootMode != modload.NoRoot {
                panic("modload.RootMode must be NoRoot")
        }
 
@@ -3404,12 +3404,12 @@ func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args
                allowed = nil
        }
        noneSelected := func(path string) (version string) { return "none" }
-       qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed)
+       qrs, err := modload.QueryPackages(loaderstate, ctx, patterns[0], version, noneSelected, allowed)
        if err != nil {
                return nil, fmt.Errorf("%s: %w", args[0], err)
        }
        rootMod := qrs[0].Mod
-       deprecation, err := modload.CheckDeprecation(ctx, rootMod)
+       deprecation, err := modload.CheckDeprecation(loaderstate, ctx, rootMod)
        if err != nil {
                return nil, fmt.Errorf("%s: %w", args[0], err)
        }
@@ -3438,12 +3438,12 @@ func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args
        // Since we are in NoRoot mode, the build list initially contains only
        // the dummy command-line-arguments module. Add a requirement on the
        // module that provides the packages named on the command line.
-       if _, err := modload.EditBuildList(ctx, nil, []module.Version{rootMod}); err != nil {
+       if _, err := modload.EditBuildList(loaderstate, ctx, nil, []module.Version{rootMod}); err != nil {
                return nil, fmt.Errorf("%s: %w", args[0], err)
        }
 
        // Load packages for all arguments.
-       pkgs := PackagesAndErrors(ctx, opts, patterns)
+       pkgs := PackagesAndErrors(loaderstate, ctx, opts, patterns)
 
        // Check that named packages are all provided by the same module.
        for _, pkg := range pkgs {
@@ -3471,14 +3471,14 @@ func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args
 }
 
 // EnsureImport ensures that package p imports the named package.
-func EnsureImport(p *Package, pkg string) {
+func EnsureImport(loaderstate *modload.State, p *Package, pkg string) {
        for _, d := range p.Internal.Imports {
                if d.Name == pkg {
                        return
                }
        }
 
-       p1, err := LoadImportWithFlags(pkg, p.Dir, p, &ImportStack{}, nil, 0)
+       p1, err := LoadImportWithFlags(loaderstate, pkg, p.Dir, p, &ImportStack{}, nil, 0)
        if err != nil {
                base.Fatalf("load %s: %v", pkg, err)
        }
@@ -3494,7 +3494,7 @@ func EnsureImport(p *Package, pkg string) {
 // "go test -cover"). It walks through the packages being built (and
 // dependencies) and marks them for coverage instrumentation when
 // appropriate, and possibly adding additional deps where needed.
-func PrepareForCoverageBuild(pkgs []*Package) {
+func PrepareForCoverageBuild(loaderstate *modload.State, pkgs []*Package) {
        var match []func(*Package) bool
 
        matchMainModAndCommandLine := func(p *Package) bool {
@@ -3507,7 +3507,7 @@ func PrepareForCoverageBuild(pkgs []*Package) {
                // the specific packages selected by the user-specified pattern(s).
                match = make([]func(*Package) bool, len(cfg.BuildCoverPkg))
                for i := range cfg.BuildCoverPkg {
-                       match[i] = MatchPackage(cfg.BuildCoverPkg[i], base.Cwd())
+                       match[i] = MatchPackage(loaderstate, cfg.BuildCoverPkg[i], base.Cwd())
                }
        } else {
                // Without -coverpkg, instrument only packages in the main module
@@ -3519,10 +3519,10 @@ func PrepareForCoverageBuild(pkgs []*Package) {
        // Visit the packages being built or installed, along with all of
        // their dependencies, and mark them to be instrumented, taking
        // into account the matchers we've set up in the sequence above.
-       SelectCoverPackages(PackageList(pkgs), match, "build")
+       SelectCoverPackages(loaderstate, PackageList(pkgs), match, "build")
 }
 
-func SelectCoverPackages(roots []*Package, match []func(*Package) bool, op string) []*Package {
+func SelectCoverPackages(loaderstate *modload.State, roots []*Package, match []func(*Package) bool, op string) []*Package {
        var warntag string
        var includeMain bool
        switch op {
@@ -3602,7 +3602,7 @@ func SelectCoverPackages(roots []*Package, match []func(*Package) bool, op strin
 
                // Force import of sync/atomic into package if atomic mode.
                if cfg.BuildCoverMode == "atomic" {
-                       EnsureImport(p, "sync/atomic")
+                       EnsureImport(loaderstate, p, "sync/atomic")
                }
        }
 
index 51c8cc0932406edc6e2f2b3152cb89ffdb13e7b2..09e32a4f46a69be165b6a089bb4b3355a20923da 100644 (file)
@@ -14,7 +14,7 @@ import (
 )
 
 // MatchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd.
-func MatchPackage(pattern, cwd string) func(*Package) bool {
+func MatchPackage(loaderstate *modload.State, pattern, cwd string) func(*Package) bool {
        switch {
        case search.IsRelativePath(pattern):
                // Split pattern into leading pattern-free directory path
@@ -54,13 +54,13 @@ func MatchPackage(pattern, cwd string) func(*Package) bool {
                return func(p *Package) bool { return p.Standard }
        case pattern == "cmd":
                return func(p *Package) bool { return p.Standard && strings.HasPrefix(p.ImportPath, "cmd/") }
-       case pattern == "tool" && modload.Enabled():
+       case pattern == "tool" && modload.Enabled(loaderstate):
                return func(p *Package) bool {
-                       return modload.LoaderState.MainModules.Tools()[p.ImportPath]
+                       return loaderstate.MainModules.Tools()[p.ImportPath]
                }
-       case pattern == "work" && modload.Enabled():
+       case pattern == "work" && modload.Enabled(loaderstate):
                return func(p *Package) bool {
-                       return p.Module != nil && modload.LoaderState.MainModules.Contains(p.Module.Path)
+                       return p.Module != nil && loaderstate.MainModules.Contains(p.Module.Path)
                }
 
        default:
index 9849ee138a578177d2e9aaac2e044d9a0894320c..9019545b4b8d82d9cdd8bc115a5a7e736f4f973a 100644 (file)
@@ -24,6 +24,7 @@ import (
        "unicode/utf8"
 
        "cmd/go/internal/fsys"
+       "cmd/go/internal/modload"
        "cmd/go/internal/str"
        "cmd/go/internal/trace"
 )
@@ -106,7 +107,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p
        defer pre.flush()
        allImports := append([]string{}, p.TestImports...)
        allImports = append(allImports, p.XTestImports...)
-       pre.preloadImports(ctx, opts, allImports, p.Internal.Build)
+       pre.preloadImports(modload.LoaderState, ctx, opts, allImports, p.Internal.Build)
 
        var ptestErr, pxtestErr *PackageError
        var imports, ximports []*Package
@@ -116,7 +117,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p
        stk.Push(ImportInfo{Pkg: p.ImportPath + " (test)"})
        rawTestImports := str.StringList(p.TestImports)
        for i, path := range p.TestImports {
-               p1, err := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
+               p1, err := loadImport(modload.LoaderState, ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
                if err != nil && ptestErr == nil {
                        ptestErr = err
                        incomplete = true
@@ -145,7 +146,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p
        var pxtestIncomplete bool
        rawXTestImports := str.StringList(p.XTestImports)
        for i, path := range p.XTestImports {
-               p1, err := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
+               p1, err := loadImport(modload.LoaderState, ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
                if err != nil && pxtestErr == nil {
                        pxtestErr = err
                }
@@ -292,7 +293,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p
        }
 
        pb := p.Internal.Build
-       pmain.DefaultGODEBUG = defaultGODEBUG(pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives)
+       pmain.DefaultGODEBUG = defaultGODEBUG(modload.LoaderState, pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives)
        if pmain.Internal.BuildInfo == nil || pmain.DefaultGODEBUG != p.DefaultGODEBUG {
                // Either we didn't generate build info for the package under test (because it wasn't package main), or
                // the DefaultGODEBUG used to build the test main package is different from the DefaultGODEBUG
@@ -321,7 +322,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p
                if dep == ptest.ImportPath {
                        pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
                } else {
-                       p1, err := loadImport(ctx, opts, pre, dep, "", nil, &stk, nil, 0)
+                       p1, err := loadImport(modload.LoaderState, ctx, opts, pre, dep, "", nil, &stk, nil, 0)
                        if err != nil && pmain.Error == nil {
                                pmain.Error = err
                                pmain.Incomplete = true
index 8df11bfa59fa4334a59b0c080984714cfcb57f3c..f4ed4b45834e891af5e5ddd6b59524dd6f5c7522 100644 (file)
@@ -109,15 +109,15 @@ type ModuleJSON struct {
 }
 
 func runDownload(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
 
        // Check whether modules are enabled and whether we're in a module.
        modload.LoaderState.ForceUseModules = true
        modload.ExplicitWriteGoMod = true
        haveExplicitArgs := len(args) > 0
 
-       if modload.HasModRoot() || modload.WorkFilePath() != "" {
-               modload.LoadModFile(ctx) // to fill MainModules
+       if modload.HasModRoot(modload.LoaderState) || modload.WorkFilePath(modload.LoaderState) != "" {
+               modload.LoadModFile(modload.LoaderState, ctx) // to fill MainModules
 
                if haveExplicitArgs {
                        for _, mainModule := range modload.LoaderState.MainModules.Versions() {
@@ -130,7 +130,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
                                        }
                                }
                        }
-               } else if modload.WorkFilePath() != "" {
+               } else if modload.WorkFilePath(modload.LoaderState) != "" {
                        // TODO(#44435): Think about what the correct query is to download the
                        // right set of modules. Also see code review comment at
                        // https://go-review.googlesource.com/c/go/+/359794/comments/ce946a80_6cf53992.
@@ -169,7 +169,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
        }
 
        if len(args) == 0 {
-               if modload.HasModRoot() {
+               if modload.HasModRoot(modload.LoaderState) {
                        os.Stderr.WriteString("go: no module dependencies to download\n")
                } else {
                        base.Errorf("go: no modules specified (see 'go help mod download')")
@@ -177,7 +177,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
                base.Exit()
        }
 
-       if *downloadReuse != "" && modload.HasModRoot() {
+       if *downloadReuse != "" && modload.HasModRoot(modload.LoaderState) {
                base.Fatalf("go mod download -reuse cannot be used inside a module")
        }
 
@@ -220,7 +220,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
                // when we can.
        }
 
-       if !haveExplicitArgs && modload.WorkFilePath() == "" {
+       if !haveExplicitArgs && modload.WorkFilePath(modload.LoaderState) == "" {
                // 'go mod download' is sometimes run without arguments to pre-populate the
                // module cache. In modules that aren't at go 1.17 or higher, it may fetch
                // modules that aren't needed to build packages in the main module. This is
@@ -291,7 +291,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
        // with no arguments we download the module pattern "all",
        // which may include dependencies that are normally pruned out
        // of the individual modules in the workspace.
-       if haveExplicitArgs || modload.WorkFilePath() != "" {
+       if haveExplicitArgs || modload.WorkFilePath(modload.LoaderState) != "" {
                var sw toolchain.Switcher
                // Add errors to the Switcher in deterministic order so that they will be
                // logged deterministically.
@@ -347,7 +347,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
        //
        // Don't save sums for 'go mod download' without arguments unless we're in
        // workspace mode; see comment above.
-       if haveExplicitArgs || modload.WorkFilePath() != "" {
+       if haveExplicitArgs || modload.WorkFilePath(modload.LoaderState) != "" {
                if err := modload.WriteGoMod(ctx, modload.WriteOpts{}); err != nil {
                        base.Error(err)
                }
index 5f47260e1882925cc085948db0a826bd89271b64..3bc6009b57b59552683e075bc6f672d514c97a7a 100644 (file)
@@ -52,7 +52,7 @@ func init() {
 }
 
 func runGraph(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
 
        if len(args) > 0 {
                base.Fatalf("go: 'go mod graph' accepts no arguments")
index 0314dcef250d81a7a9bf1d13a08d2e7070bba4b5..c693bd52a38af966660f3a3f08858720b45cd5b4 100644 (file)
@@ -130,7 +130,7 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
                })
        }
 
-       modload.LoadPackages(ctx, modload.PackageOpts{
+       modload.LoadPackages(modload.LoaderState, ctx, modload.PackageOpts{
                TidyGoVersion:            tidyGo.String(),
                Tags:                     imports.AnyTags(),
                Tidy:                     true,
index df673e885c1473f519c6f83490869170e7d22422..8d9672d5365523677c5c78a621106a16cabe1c59 100644 (file)
@@ -66,8 +66,8 @@ func init() {
 }
 
 func runVendor(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
-       if modload.WorkFilePath() != "" {
+       modload.InitWorkfile(modload.LoaderState)
+       if modload.WorkFilePath(modload.LoaderState) != "" {
                base.Fatalf("go: 'go mod vendor' cannot be run in workspace mode. Run 'go work vendor' to vendor the workspace or set 'GOWORK=off' to exit workspace mode.")
        }
        RunVendor(ctx, vendorE, vendorO, args)
@@ -88,7 +88,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string)
                AllowErrors:              vendorE,
                SilenceMissingStdImports: true,
        }
-       _, pkgs := modload.LoadPackages(ctx, loadOpts, "all")
+       _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all")
 
        var vdir string
        switch {
@@ -97,7 +97,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string)
        case vendorO != "":
                vdir = filepath.Join(base.Cwd(), vendorO)
        default:
-               vdir = filepath.Join(modload.VendorDir())
+               vdir = filepath.Join(modload.VendorDir(modload.LoaderState))
        }
        if err := os.RemoveAll(vdir); err != nil {
                base.Fatal(err)
@@ -116,8 +116,8 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string)
        includeAllReplacements := false
        includeGoVersions := false
        isExplicit := map[module.Version]bool{}
-       gv := modload.LoaderState.MainModules.GoVersion()
-       if gover.Compare(gv, "1.14") >= 0 && (modload.FindGoWork(base.Cwd()) != "" || modload.ModFile().Go != nil) {
+       gv := modload.LoaderState.MainModules.GoVersion(modload.LoaderState)
+       if gover.Compare(gv, "1.14") >= 0 && (modload.FindGoWork(modload.LoaderState, base.Cwd()) != "" || modload.ModFile().Go != nil) {
                // If the Go version is at least 1.14, annotate all explicit 'require' and
                // 'replace' targets found in the go.mod file so that we can perform a
                // stronger consistency check when -mod=vendor is set.
@@ -162,7 +162,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string)
 
        replacementWritten := make(map[module.Version]bool)
        for _, m := range vendorMods {
-               replacement := modload.Replacement(m)
+               replacement := modload.Replacement(modload.LoaderState, m)
                line := moduleLine(m, replacement)
                replacementWritten[m] = true
                io.WriteString(w, line)
@@ -215,7 +215,7 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string)
                                                continue
                                        }
                                        replacementWritten[r.Old] = true
-                                       rNew := modload.Replacement(r.Old)
+                                       rNew := modload.Replacement(modload.LoaderState, r.Old)
                                        if rNew == (module.Version{}) {
                                                // There is no replacement. Don't try to write it.
                                                continue
@@ -269,7 +269,7 @@ func moduleLine(m, r module.Version) string {
 }
 
 func vendorPkg(vdir, pkg string) {
-       src, realPath, _ := modload.Lookup("", false, pkg)
+       src, realPath, _ := modload.Lookup(modload.LoaderState, "", false, pkg)
        if src == "" {
                base.Errorf("internal error: no pkg for %s\n", pkg)
                return
@@ -315,7 +315,7 @@ func vendorPkg(vdir, pkg string) {
                }
        }
        var embedPatterns []string
-       if gover.Compare(modload.LoaderState.MainModules.GoVersion(), "1.22") >= 0 {
+       if gover.Compare(modload.LoaderState.MainModules.GoVersion(modload.LoaderState), "1.22") >= 0 {
                embedPatterns = bp.EmbedPatterns
        } else {
                // Maintain the behavior of https://github.com/golang/go/issues/63473
@@ -431,7 +431,7 @@ func matchPotentialSourceFile(dir string, info fs.DirEntry) bool {
                return false
        }
        if info.Name() == "go.mod" || info.Name() == "go.sum" {
-               if gv := modload.LoaderState.MainModules.GoVersion(); gover.Compare(gv, "1.17") >= 0 {
+               if gv := modload.LoaderState.MainModules.GoVersion(modload.LoaderState); gover.Compare(gv, "1.17") >= 0 {
                        // As of Go 1.17, we strip go.mod and go.sum files from dependency modules.
                        // Otherwise, 'go' commands invoked within the vendor subtree may misidentify
                        // an arbitrary directory within the vendor tree as a module root.
index 8de444ff06ad1def5c1c26dab15624ede64f5744..d8227bcd5455a3d80b05d9ecef6cc5369d10da59 100644 (file)
@@ -44,7 +44,7 @@ func init() {
 }
 
 func runVerify(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
 
        if len(args) != 0 {
                // NOTE(rsc): Could take a module pattern.
index 62a5387ed8841c91629a454668b88889dc3ddac1..b37d9fded0f47c435605ce785a3826570af34414 100644 (file)
@@ -63,7 +63,7 @@ func init() {
 }
 
 func runWhy(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
        modload.LoaderState.ForceUseModules = true
        modload.LoaderState.RootMode = modload.NeedRoot
        modload.ExplicitWriteGoMod = true // don't write go.mod in ListModules
@@ -89,7 +89,7 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) {
                }
 
                byModule := make(map[string][]string)
-               _, pkgs := modload.LoadPackages(ctx, loadOpts, "all")
+               _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all")
                for _, path := range pkgs {
                        m := modload.PackageModule(path)
                        if m.Path != "" {
@@ -120,9 +120,9 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) {
                }
        } else {
                // Resolve to packages.
-               matches, _ := modload.LoadPackages(ctx, loadOpts, args...)
+               matches, _ := modload.LoadPackages(modload.LoaderState, ctx, loadOpts, args...)
 
-               modload.LoadPackages(ctx, loadOpts, "all") // rebuild graph, from main module (not from named packages)
+               modload.LoadPackages(modload.LoaderState, ctx, loadOpts, "all") // rebuild graph, from main module (not from named packages)
 
                sep := ""
                for _, m := range matches {
index 16cc1457058933366d1826c5ecefa08522f00078..9d59d1a8ea82189489eb634c0d76921dea9b0d6c 100644 (file)
@@ -94,7 +94,7 @@ func TestZipSums(t *testing.T) {
 
        cfg.GOPROXY = "direct"
        cfg.GOSUMDB = "off"
-       modload.Init()
+       modload.Init(modload.LoaderState)
 
        // Shard tests by downloading only every nth module when shard flags are set.
        // This makes it easier to test small groups of modules quickly. We avoid
index 5017f878ed3647e6a26699fbbcb3d9da86a7a05f..141e1708fa6dedbd3ecb9dc0dfaf7c1450d15bdd 100644 (file)
@@ -307,14 +307,14 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
 
        // Allow looking up modules for import paths when outside of a module.
        // 'go get' is expected to do this, unlike other commands.
-       modload.AllowMissingModuleImports()
+       modload.AllowMissingModuleImports(modload.LoaderState)
 
        // 'go get' no longer builds or installs packages, so there's nothing to do
        // if there's no go.mod file.
        // TODO(#40775): make modload.Init return ErrNoModRoot instead of exiting.
        // We could handle that here by printing a different message.
-       modload.Init()
-       if !modload.HasModRoot() {
+       modload.Init(modload.LoaderState)
+       if !modload.HasModRoot(modload.LoaderState) {
                base.Fatalf("go: go.mod file not found in current directory or any parent directory.\n" +
                        "\t'go get' is no longer supported outside a module.\n" +
                        "\tTo build and install a command, use 'go install' with a version,\n" +
@@ -424,9 +424,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
        newReqs := reqsFromGoMod(modload.ModFile())
        r.reportChanges(oldReqs, newReqs)
 
-       if gowork := modload.FindGoWork(base.Cwd()); gowork != "" {
+       if gowork := modload.FindGoWork(modload.LoaderState, base.Cwd()); gowork != "" {
                wf, err := modload.ReadWorkFile(gowork)
-               if err == nil && modload.UpdateWorkGoVersion(wf, modload.LoaderState.MainModules.GoVersion()) {
+               if err == nil && modload.UpdateWorkGoVersion(wf, modload.LoaderState.MainModules.GoVersion(modload.LoaderState)) {
                        modload.WriteWorkFile(gowork, wf)
                }
        }
@@ -448,7 +448,7 @@ func updateTools(ctx context.Context, queries []*query, opts *modload.WriteOpts)
                patterns = append(patterns, q.pattern)
        }
 
-       matches, _ := modload.LoadPackages(ctx, pkgOpts, patterns...)
+       matches, _ := modload.LoadPackages(modload.LoaderState, ctx, pkgOpts, patterns...)
        for i, m := range matches {
                if queries[i].version == "none" {
                        opts.DropTools = append(opts.DropTools, m.Pkgs...)
@@ -574,7 +574,7 @@ func newResolver(ctx context.Context, queries []*query) *resolver {
                buildListVersion: initialVersion,
                initialVersion:   initialVersion,
                nonesByPath:      map[string]*query{},
-               workspace:        loadWorkspace(modload.FindGoWork(base.Cwd())),
+               workspace:        loadWorkspace(modload.FindGoWork(modload.LoaderState, base.Cwd())),
        }
 
        for _, q := range queries {
@@ -645,7 +645,7 @@ func (r *resolver) noneForPath(mPath string) (nq *query, found bool) {
 // allowed versions.
 func (r *resolver) queryModule(ctx context.Context, mPath, query string, selected func(string) string) (module.Version, error) {
        current := r.initialSelected(mPath)
-       rev, err := modload.Query(ctx, mPath, query, current, r.checkAllowedOr(query, selected))
+       rev, err := modload.Query(modload.LoaderState, ctx, mPath, query, current, r.checkAllowedOr(query, selected))
        if err != nil {
                return module.Version{}, err
        }
@@ -655,7 +655,7 @@ func (r *resolver) queryModule(ctx context.Context, mPath, query string, selecte
 // queryPackages wraps modload.QueryPackage, substituting r.checkAllowedOr to
 // decide allowed versions.
 func (r *resolver) queryPackages(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, err error) {
-       results, err := modload.QueryPackages(ctx, pattern, query, selected, r.checkAllowedOr(query, selected))
+       results, err := modload.QueryPackages(modload.LoaderState, ctx, pattern, query, selected, r.checkAllowedOr(query, selected))
        if len(results) > 0 {
                pkgMods = make([]module.Version, 0, len(results))
                for _, qr := range results {
@@ -668,7 +668,7 @@ func (r *resolver) queryPackages(ctx context.Context, pattern, query string, sel
 // queryPattern wraps modload.QueryPattern, substituting r.checkAllowedOr to
 // decide allowed versions.
 func (r *resolver) queryPattern(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, mod module.Version, err error) {
-       results, modOnly, err := modload.QueryPattern(ctx, pattern, query, selected, r.checkAllowedOr(query, selected))
+       results, modOnly, err := modload.QueryPattern(modload.LoaderState, ctx, pattern, query, selected, r.checkAllowedOr(query, selected))
        if len(results) > 0 {
                pkgMods = make([]module.Version, 0, len(results))
                for _, qr := range results {
@@ -721,7 +721,7 @@ func (r *resolver) queryNone(ctx context.Context, q *query) {
 
        if !q.isWildcard() {
                q.pathOnce(q.pattern, func() pathSet {
-                       hasModRoot := modload.HasModRoot()
+                       hasModRoot := modload.HasModRoot(modload.LoaderState)
                        if hasModRoot && modload.LoaderState.MainModules.Contains(q.pattern) {
                                v := module.Version{Path: q.pattern}
                                // The user has explicitly requested to downgrade their own module to
@@ -746,7 +746,7 @@ func (r *resolver) queryNone(ctx context.Context, q *query) {
                        continue
                }
                q.pathOnce(curM.Path, func() pathSet {
-                       if modload.HasModRoot() && curM.Version == "" && modload.LoaderState.MainModules.Contains(curM.Path) {
+                       if modload.HasModRoot(modload.LoaderState) && curM.Version == "" && modload.LoaderState.MainModules.Contains(curM.Path) {
                                return errSet(&modload.QueryMatchesMainModulesError{MainModules: []module.Version{curM}, Pattern: q.pattern, Query: q.version})
                        }
                        return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}}
@@ -766,7 +766,7 @@ func (r *resolver) performLocalQueries(ctx context.Context) {
 
                        // Absolute paths like C:\foo and relative paths like ../foo... are
                        // restricted to matching packages in the main module.
-                       pkgPattern, mainModule := modload.LoaderState.MainModules.DirImportPath(ctx, q.pattern)
+                       pkgPattern, mainModule := modload.LoaderState.MainModules.DirImportPath(modload.LoaderState, ctx, q.pattern)
                        if pkgPattern == "." {
                                modload.MustHaveModRoot()
                                versions := modload.LoaderState.MainModules.Versions()
@@ -1275,13 +1275,13 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack
                return nil
        }
 
-       _, pkgs := modload.LoadPackages(ctx, opts, patterns...)
+       _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, opts, patterns...)
        for _, pkgPath := range pkgs {
                const (
                        parentPath  = ""
                        parentIsStd = false
                )
-               _, _, err := modload.Lookup(parentPath, parentIsStd, pkgPath)
+               _, _, err := modload.Lookup(modload.LoaderState, parentPath, parentIsStd, pkgPath)
                if err == nil {
                        continue
                }
@@ -1651,7 +1651,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
                        AllowErrors:              true,
                        SilenceNoGoErrors:        true,
                }
-               matches, pkgs := modload.LoadPackages(ctx, pkgOpts, pkgPatterns...)
+               matches, pkgs := modload.LoadPackages(modload.LoaderState, ctx, pkgOpts, pkgPatterns...)
                for _, m := range matches {
                        if len(m.Errs) > 0 {
                                base.SetExitStatus(1)
@@ -1659,7 +1659,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
                        }
                }
                for _, pkg := range pkgs {
-                       if dir, _, err := modload.Lookup("", false, pkg); err != nil {
+                       if dir, _, err := modload.Lookup(modload.LoaderState, "", false, pkg); err != nil {
                                if dir != "" && errors.Is(err, imports.ErrNoGo) {
                                        // Since dir is non-empty, we must have located source files
                                        // associated with either the package or its test — ErrNoGo must
@@ -1690,7 +1690,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
                }
        }
 
-       reqs := modload.LoadModFile(ctx)
+       reqs := modload.LoadModFile(modload.LoaderState, ctx)
        for m := range relevantMods {
                if reqs.IsDirect(m.Path) {
                        relevantMods[m] |= direct
@@ -1714,7 +1714,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
        for i := range retractions {
                i := i
                r.work.Add(func() {
-                       err := modload.CheckRetractions(ctx, retractions[i].m)
+                       err := modload.CheckRetractions(modload.LoaderState, ctx, retractions[i].m)
                        if _, ok := errors.AsType[*modload.ModuleRetractedError](err); ok {
                                retractions[i].message = err.Error()
                        }
@@ -1735,7 +1735,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
        for i := range deprecations {
                i := i
                r.work.Add(func() {
-                       deprecation, err := modload.CheckDeprecation(ctx, deprecations[i].m)
+                       deprecation, err := modload.CheckDeprecation(modload.LoaderState, ctx, deprecations[i].m)
                        if err != nil || deprecation == "" {
                                return
                        }
@@ -1765,7 +1765,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
                i := i
                m := r.buildList[i]
                mActual := m
-               if mRepl := modload.Replacement(m); mRepl.Path != "" {
+               if mRepl := modload.Replacement(modload.LoaderState, m); mRepl.Path != "" {
                        mActual = mRepl
                }
                old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]}
@@ -1773,7 +1773,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
                        continue
                }
                oldActual := old
-               if oldRepl := modload.Replacement(old); oldRepl.Path != "" {
+               if oldRepl := modload.Replacement(modload.LoaderState, old); oldRepl.Path != "" {
                        oldActual = oldRepl
                }
                if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(oldActual) {
@@ -1986,7 +1986,7 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi
                }
        }
 
-       changed, err := modload.EditBuildList(ctx, additions, resolved)
+       changed, err := modload.EditBuildList(modload.LoaderState, ctx, additions, resolved)
        if err != nil {
                if errors.Is(err, gover.ErrTooNew) {
                        toolchain.SwitchOrFatal(ctx, err)
index 59f3023ffc4f41950cda76c892a8b2d49a53da26..7076bbadce898b005f77e3312a69b57028579b58 100644 (file)
@@ -184,7 +184,7 @@ func (q *query) validate() error {
 
        if q.pattern == "all" {
                // If there is no main module, "all" is not meaningful.
-               if !modload.HasModRoot() {
+               if !modload.HasModRoot(modload.LoaderState) {
                        return fmt.Errorf(`cannot match "all": %v`, modload.ErrNoModRoot)
                }
                if !versionOkForMainModule(q.version) {
index a8ab82d1ecb2461267e8cb0cfb957231a18d2ea6..5b1b643d272dfd5206d052cae9ad2026d132b2eb 100644 (file)
@@ -51,8 +51,8 @@ func findStandardImportPath(path string) string {
 // a given package. If modules are not enabled or if the package is in the
 // standard library or if the package was not successfully loaded with
 // LoadPackages or ImportFromFiles, nil is returned.
-func PackageModuleInfo(ctx context.Context, pkgpath string) *modinfo.ModulePublic {
-       if isStandardImportPath(pkgpath) || !Enabled() {
+func PackageModuleInfo(loaderstate *State, ctx context.Context, pkgpath string) *modinfo.ModulePublic {
+       if isStandardImportPath(pkgpath) || !Enabled(loaderstate) {
                return nil
        }
        m, ok := findModule(loaded, pkgpath)
@@ -60,23 +60,23 @@ func PackageModuleInfo(ctx context.Context, pkgpath string) *modinfo.ModulePubli
                return nil
        }
 
-       rs := LoadModFile(ctx)
-       return moduleInfo(ctx, rs, m, 0, nil)
+       rs := LoadModFile(loaderstate, ctx)
+       return moduleInfo(loaderstate, ctx, rs, m, 0, nil)
 }
 
 // PackageModRoot returns the module root directory for the module that provides
 // a given package. If modules are not enabled or if the package is in the
 // standard library or if the package was not successfully loaded with
 // LoadPackages or ImportFromFiles, the empty string is returned.
-func PackageModRoot(ctx context.Context, pkgpath string) string {
-       if isStandardImportPath(pkgpath) || !Enabled() || cfg.BuildMod == "vendor" {
+func PackageModRoot(loaderstate *State, ctx context.Context, pkgpath string) string {
+       if isStandardImportPath(pkgpath) || !Enabled(loaderstate) || cfg.BuildMod == "vendor" {
                return ""
        }
        m, ok := findModule(loaded, pkgpath)
        if !ok {
                return ""
        }
-       root, _, err := fetch(ctx, m)
+       root, _, err := fetch(loaderstate, ctx, m)
        if err != nil {
                return ""
        }
@@ -84,26 +84,26 @@ func PackageModRoot(ctx context.Context, pkgpath string) string {
 }
 
 func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
-       if !Enabled() {
+       if !Enabled(LoaderState) {
                return nil
        }
 
        if path, vers, found := strings.Cut(path, "@"); found {
                m := module.Version{Path: path, Version: vers}
-               return moduleInfo(ctx, nil, m, 0, nil)
+               return moduleInfo(LoaderState, ctx, nil, m, 0, nil)
        }
 
-       rs := LoadModFile(ctx)
+       rs := LoadModFile(LoaderState, ctx)
 
        var (
                v  string
                ok bool
        )
        if rs.pruning == pruned {
-               v, ok = rs.rootSelected(path)
+               v, ok = rs.rootSelected(LoaderState, path)
        }
        if !ok {
-               mg, err := rs.Graph(ctx)
+               mg, err := rs.Graph(LoaderState, ctx)
                if err != nil {
                        base.Fatal(err)
                }
@@ -119,7 +119,7 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
                }
        }
 
-       return moduleInfo(ctx, rs, module.Version{Path: path, Version: v}, 0, nil)
+       return moduleInfo(LoaderState, ctx, rs, module.Version{Path: path, Version: v}, 0, nil)
 }
 
 // addUpdate fills in m.Update if an updated version is available.
@@ -128,7 +128,7 @@ func addUpdate(ctx context.Context, m *modinfo.ModulePublic) {
                return
        }
 
-       info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed)
+       info, err := Query(LoaderState, ctx, m.Path, "upgrade", m.Version, CheckAllowed)
        if _, ok := errors.AsType[*NoMatchingVersionError](err); ok ||
                errors.Is(err, fs.ErrNotExist) ||
                errors.Is(err, ErrDisallowed) {
@@ -221,7 +221,7 @@ func addVersions(ctx context.Context, m *modinfo.ModulePublic, listRetracted boo
        if listRetracted {
                allowed = CheckExclusions
        }
-       v, origin, err := versions(ctx, m.Path, allowed)
+       v, origin, err := versions(LoaderState, ctx, m.Path, allowed)
        if err != nil && m.Error == nil {
                m.Error = &modinfo.ModuleError{Err: err.Error()}
        }
@@ -231,12 +231,12 @@ func addVersions(ctx context.Context, m *modinfo.ModulePublic, listRetracted boo
 
 // addRetraction fills in m.Retracted if the module was retracted by its author.
 // m.Error is set if there's an error loading retraction information.
-func addRetraction(ctx context.Context, m *modinfo.ModulePublic) {
+func addRetraction(loaderstate *State, ctx context.Context, m *modinfo.ModulePublic) {
        if m.Version == "" {
                return
        }
 
-       err := CheckRetractions(ctx, module.Version{Path: m.Path, Version: m.Version})
+       err := CheckRetractions(loaderstate, ctx, module.Version{Path: m.Path, Version: m.Version})
        if err == nil {
                return
        } else if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) {
@@ -263,7 +263,7 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) {
 // addDeprecation fills in m.Deprecated if the module was deprecated by its
 // author. m.Error is set if there's an error loading deprecation information.
 func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) {
-       deprecation, err := CheckDeprecation(ctx, module.Version{Path: m.Path, Version: m.Version})
+       deprecation, err := CheckDeprecation(LoaderState, ctx, module.Version{Path: m.Path, Version: m.Version})
        if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) {
                // Ignore "no matching version" and "not found" errors.
                // This means the proxy has no matching version or no versions at all.
@@ -287,8 +287,8 @@ func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) {
 // moduleInfo returns information about module m, loaded from the requirements
 // in rs (which may be nil to indicate that m was not loaded from a requirement
 // graph).
-func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode ListMode, reuse map[module.Version]*modinfo.ModulePublic) *modinfo.ModulePublic {
-       if m.Version == "" && LoaderState.MainModules.Contains(m.Path) {
+func moduleInfo(loaderstate *State, ctx context.Context, rs *Requirements, m module.Version, mode ListMode, reuse map[module.Version]*modinfo.ModulePublic) *modinfo.ModulePublic {
+       if m.Version == "" && loaderstate.MainModules.Contains(m.Path) {
                info := &modinfo.ModulePublic{
                        Path:    m.Path,
                        Version: m.Version,
@@ -299,7 +299,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
                } else {
                        panic("internal error: GoVersion not set for main module")
                }
-               if modRoot := LoaderState.MainModules.ModRoot(m); modRoot != "" {
+               if modRoot := loaderstate.MainModules.ModRoot(m); modRoot != "" {
                        info.Dir = modRoot
                        info.GoMod = modFilePath(modRoot)
                }
@@ -322,7 +322,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
                }
 
                checksumOk := func(suffix string) bool {
-                       return rs == nil || m.Version == "" || !mustHaveSums() ||
+                       return rs == nil || m.Version == "" || !mustHaveSums(loaderstate) ||
                                modfetch.HaveSum(module.Version{Path: m.Path, Version: m.Version + suffix})
                }
 
@@ -330,7 +330,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
 
                if m.Version != "" {
                        if old := reuse[mod]; old != nil {
-                               if err := checkReuse(ctx, mod, old.Origin); err == nil {
+                               if err := checkReuse(loaderstate, ctx, mod, old.Origin); err == nil {
                                        *m = *old
                                        m.Query = ""
                                        m.Dir = ""
@@ -338,7 +338,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
                                }
                        }
 
-                       if q, err := Query(ctx, m.Path, m.Version, "", nil); err != nil {
+                       if q, err := Query(loaderstate, ctx, m.Path, m.Version, "", nil); err != nil {
                                m.Error = &modinfo.ModuleError{Err: err.Error()}
                        } else {
                                m.Version = q.Version
@@ -349,7 +349,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
                if m.GoVersion == "" && checksumOk("/go.mod") {
                        // Load the go.mod file to determine the Go version, since it hasn't
                        // already been populated from rawGoVersion.
-                       if summary, err := rawGoModSummary(mod); err == nil && summary.goVersion != "" {
+                       if summary, err := rawGoModSummary(loaderstate, mod); err == nil && summary.goVersion != "" {
                                m.GoVersion = summary.goVersion
                        }
                }
@@ -377,7 +377,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
                        }
 
                        if mode&ListRetracted != 0 {
-                               addRetraction(ctx, m)
+                               addRetraction(loaderstate, ctx, m)
                        }
                }
        }
@@ -389,7 +389,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
                return info
        }
 
-       r := Replacement(m)
+       r := Replacement(loaderstate, m)
        if r.Path == "" {
                if cfg.BuildMod == "vendor" {
                        // It's tempting to fill in the "Dir" field to point within the vendor
@@ -418,7 +418,7 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
                if filepath.IsAbs(r.Path) {
                        info.Replace.Dir = r.Path
                } else {
-                       info.Replace.Dir = filepath.Join(replaceRelativeTo(), r.Path)
+                       info.Replace.Dir = filepath.Join(replaceRelativeTo(loaderstate), r.Path)
                }
                info.Replace.GoMod = filepath.Join(info.Replace.Dir, "go.mod")
        }
index cf64ee1dc210f90ce50717f4627d31923b343251..54ec4d23ebe08e0983a5e12ced9fc02037975a77 100644 (file)
@@ -104,21 +104,21 @@ func mustHaveGoRoot(roots []module.Version) {
 //
 // If vendoring is in effect, the caller must invoke initVendor on the returned
 // *Requirements before any other method.
-func newRequirements(pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements {
+func newRequirements(loaderstate *State, pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements {
        mustHaveGoRoot(rootModules)
 
        if pruning != workspace {
-               if LoaderState.workFilePath != "" {
+               if loaderstate.workFilePath != "" {
                        panic("in workspace mode, but pruning is not workspace in newRequirements")
                }
        }
 
        if pruning != workspace {
-               if LoaderState.workFilePath != "" {
+               if loaderstate.workFilePath != "" {
                        panic("in workspace mode, but pruning is not workspace in newRequirements")
                }
                for i, m := range rootModules {
-                       if m.Version == "" && LoaderState.MainModules.Contains(m.Path) {
+                       if m.Version == "" && loaderstate.MainModules.Contains(m.Path) {
                                panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is a main module", i))
                        }
                        if m.Path == "" || m.Version == "" {
@@ -162,10 +162,10 @@ func (rs *Requirements) String() string {
 // initVendor initializes rs.graph from the given list of vendored module
 // dependencies, overriding the graph that would normally be loaded from module
 // requirements.
-func (rs *Requirements) initVendor(vendorList []module.Version) {
+func (rs *Requirements) initVendor(loaderstate *State, vendorList []module.Version) {
        rs.graphOnce.Do(func() {
-               roots := LoaderState.MainModules.Versions()
-               if inWorkspaceMode() {
+               roots := loaderstate.MainModules.Versions()
+               if inWorkspaceMode(loaderstate) {
                        // Use rs.rootModules to pull in the go and toolchain roots
                        // from the go.work file and preserve the invariant that all
                        // of rs.rootModules are in mg.g.
@@ -176,7 +176,7 @@ func (rs *Requirements) initVendor(vendorList []module.Version) {
                }
 
                if rs.pruning == pruned {
-                       mainModule := LoaderState.MainModules.mustGetSingleMainModule()
+                       mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate)
                        // The roots of a single pruned module should already include every module in the
                        // vendor list, because the vendored modules are the same as those needed
                        // for graph pruning.
@@ -184,7 +184,7 @@ func (rs *Requirements) initVendor(vendorList []module.Version) {
                        // Just to be sure, we'll double-check that here.
                        inconsistent := false
                        for _, m := range vendorList {
-                               if v, ok := rs.rootSelected(m.Path); !ok || v != m.Version {
+                               if v, ok := rs.rootSelected(loaderstate, m.Path); !ok || v != m.Version {
                                        base.Errorf("go: vendored module %v should be required explicitly in go.mod", m)
                                        inconsistent = true
                                }
@@ -208,15 +208,15 @@ func (rs *Requirements) initVendor(vendorList []module.Version) {
                        // graph, but still distinguishes between direct and indirect
                        // dependencies.
                        vendorMod := module.Version{Path: "vendor/modules.txt", Version: ""}
-                       if inWorkspaceMode() {
-                               for _, m := range LoaderState.MainModules.Versions() {
-                                       reqs, _ := rootsFromModFile(m, LoaderState.MainModules.ModFile(m), omitToolchainRoot)
+                       if inWorkspaceMode(loaderstate) {
+                               for _, m := range loaderstate.MainModules.Versions() {
+                                       reqs, _ := rootsFromModFile(loaderstate, m, loaderstate.MainModules.ModFile(m), omitToolchainRoot)
                                        mg.g.Require(m, append(reqs, vendorMod))
                                }
                                mg.g.Require(vendorMod, vendorList)
 
                        } else {
-                               mainModule := LoaderState.MainModules.mustGetSingleMainModule()
+                               mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate)
                                mg.g.Require(mainModule, append(rs.rootModules, vendorMod))
                                mg.g.Require(vendorMod, vendorList)
                        }
@@ -227,8 +227,8 @@ func (rs *Requirements) initVendor(vendorList []module.Version) {
 }
 
 // GoVersion returns the Go language version for the Requirements.
-func (rs *Requirements) GoVersion() string {
-       v, _ := rs.rootSelected("go")
+func (rs *Requirements) GoVersion(loaderstate *State) string {
+       v, _ := rs.rootSelected(loaderstate, "go")
        if v == "" {
                panic("internal error: missing go version in modload.Requirements")
        }
@@ -238,8 +238,8 @@ func (rs *Requirements) GoVersion() string {
 // rootSelected returns the version of the root dependency with the given module
 // path, or the zero module.Version and ok=false if the module is not a root
 // dependency.
-func (rs *Requirements) rootSelected(path string) (version string, ok bool) {
-       if LoaderState.MainModules.Contains(path) {
+func (rs *Requirements) rootSelected(loaderstate *State, path string) (version string, ok bool) {
+       if loaderstate.MainModules.Contains(path) {
                return "", true
        }
        if v, ok := rs.maxRootVersion[path]; ok {
@@ -252,9 +252,9 @@ func (rs *Requirements) rootSelected(path string) (version string, ok bool) {
 // of the same module or a requirement on any version of the main module.
 // Redundant requirements should be pruned, but they may influence version
 // selection.
-func (rs *Requirements) hasRedundantRoot() bool {
+func (rs *Requirements) hasRedundantRoot(loaderstate *State) bool {
        for i, m := range rs.rootModules {
-               if LoaderState.MainModules.Contains(m.Path) || (i > 0 && m.Path == rs.rootModules[i-1].Path) {
+               if loaderstate.MainModules.Contains(m.Path) || (i > 0 && m.Path == rs.rootModules[i-1].Path) {
                        return true
                }
        }
@@ -269,9 +269,9 @@ func (rs *Requirements) hasRedundantRoot() bool {
 //
 // If the requirements of any relevant module fail to load, Graph also
 // returns a non-nil error of type *mvs.BuildListError.
-func (rs *Requirements) Graph(ctx context.Context) (*ModuleGraph, error) {
+func (rs *Requirements) Graph(loaderstate *State, ctx context.Context) (*ModuleGraph, error) {
        rs.graphOnce.Do(func() {
-               mg, mgErr := readModGraph(ctx, rs.pruning, rs.rootModules, nil)
+               mg, mgErr := readModGraph(loaderstate, ctx, rs.pruning, rs.rootModules, nil)
                rs.graph.Store(&cachedGraph{mg, mgErr})
        })
        cached := rs.graph.Load()
@@ -307,7 +307,7 @@ var readModGraphDebugOnce sync.Once
 //
 // Unlike LoadModGraph, readModGraph does not attempt to diagnose or update
 // inconsistent roots.
-func readModGraph(ctx context.Context, pruning modPruning, roots []module.Version, unprune map[module.Version]bool) (*ModuleGraph, error) {
+func readModGraph(loaderstate *State, ctx context.Context, pruning modPruning, roots []module.Version, unprune map[module.Version]bool) (*ModuleGraph, error) {
        mustHaveGoRoot(roots)
        if pruning == pruned {
                // Enable diagnostics for lazy module loading
@@ -333,10 +333,10 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio
        }
 
        var graphRoots []module.Version
-       if inWorkspaceMode() {
+       if inWorkspaceMode(loaderstate) {
                graphRoots = roots
        } else {
-               graphRoots = LoaderState.MainModules.Versions()
+               graphRoots = loaderstate.MainModules.Versions()
        }
        var (
                mu       sync.Mutex // guards mg.g and hasError during loading
@@ -347,10 +347,10 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio
        )
 
        if pruning != workspace {
-               if inWorkspaceMode() {
+               if inWorkspaceMode(loaderstate) {
                        panic("pruning is not workspace in workspace mode")
                }
-               mg.g.Require(LoaderState.MainModules.mustGetSingleMainModule(), roots)
+               mg.g.Require(loaderstate.MainModules.mustGetSingleMainModule(loaderstate), roots)
        }
 
        type dedupKey struct {
@@ -367,7 +367,7 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio
        // m's go.mod file indicates that it supports graph pruning.
        loadOne := func(m module.Version) (*modFileSummary, error) {
                return mg.loadCache.Do(m, func() (*modFileSummary, error) {
-                       summary, err := goModSummary(m)
+                       summary, err := goModSummary(loaderstate, m)
 
                        mu.Lock()
                        if err == nil {
@@ -527,12 +527,12 @@ func (mg *ModuleGraph) findError() error {
        return nil
 }
 
-func (mg *ModuleGraph) allRootsSelected() bool {
+func (mg *ModuleGraph) allRootsSelected(loaderstate *State) bool {
        var roots []module.Version
-       if inWorkspaceMode() {
-               roots = LoaderState.MainModules.Versions()
+       if inWorkspaceMode(loaderstate) {
+               roots = loaderstate.MainModules.Versions()
        } else {
-               roots, _ = mg.g.RequiredBy(LoaderState.MainModules.mustGetSingleMainModule())
+               roots, _ = mg.g.RequiredBy(loaderstate.MainModules.mustGetSingleMainModule(loaderstate))
        }
        for _, m := range roots {
                if mg.Selected(m.Path) != m.Version {
@@ -553,13 +553,13 @@ func (mg *ModuleGraph) allRootsSelected() bool {
 // LoadModGraph need only be called if LoadPackages is not,
 // typically in commands that care about modules but no particular package.
 func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) {
-       rs, err := loadModFile(ctx, nil)
+       rs, err := loadModFile(LoaderState, ctx, nil)
        if err != nil {
                return nil, err
        }
 
        if goVersion != "" {
-               v, _ := rs.rootSelected("go")
+               v, _ := rs.rootSelected(LoaderState, "go")
                if gover.Compare(v, gover.GoStrictVersion) >= 0 && gover.Compare(goVersion, v) < 0 {
                        return nil, fmt.Errorf("requested Go version %s cannot load module graph (requires Go >= %s)", goVersion, v)
                }
@@ -569,13 +569,13 @@ func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) {
                        // Use newRequirements instead of convertDepth because convertDepth
                        // also updates roots; here, we want to report the unmodified roots
                        // even though they may seem inconsistent.
-                       rs = newRequirements(unpruned, rs.rootModules, rs.direct)
+                       rs = newRequirements(LoaderState, unpruned, rs.rootModules, rs.direct)
                }
 
-               return rs.Graph(ctx)
+               return rs.Graph(LoaderState, ctx)
        }
 
-       rs, mg, err := expandGraph(ctx, rs)
+       rs, mg, err := expandGraph(LoaderState, ctx, rs)
        if err != nil {
                return nil, err
        }
@@ -594,22 +594,22 @@ func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) {
 // from those roots and any error encountered while loading that graph.
 // expandGraph returns non-nil requirements and a non-nil graph regardless of
 // errors. On error, the roots might not be updated to be consistent.
-func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleGraph, error) {
-       mg, mgErr := rs.Graph(ctx)
+func expandGraph(loaderstate *State, ctx context.Context, rs *Requirements) (*Requirements, *ModuleGraph, error) {
+       mg, mgErr := rs.Graph(loaderstate, ctx)
        if mgErr != nil {
                // Without the graph, we can't update the roots: we don't know which
                // versions of transitive dependencies would be selected.
                return rs, mg, mgErr
        }
 
-       if !mg.allRootsSelected() {
+       if !mg.allRootsSelected(loaderstate) {
                // The roots of rs are not consistent with the rest of the graph. Update
                // them. In an unpruned module this is a no-op for the build list as a whole —
                // it just promotes what were previously transitive requirements to be
                // roots — but in a pruned module it may pull in previously-irrelevant
                // transitive dependencies.
 
-               newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil, false)
+               newRS, rsErr := updateRoots(loaderstate, ctx, rs.direct, rs, nil, nil, false)
                if rsErr != nil {
                        // Failed to update roots, perhaps because of an error in a transitive
                        // dependency needed for the update. Return the original Requirements
@@ -617,7 +617,7 @@ func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleG
                        return rs, mg, rsErr
                }
                rs = newRS
-               mg, mgErr = rs.Graph(ctx)
+               mg, mgErr = rs.Graph(loaderstate, ctx)
        }
 
        return rs, mg, mgErr
@@ -639,16 +639,16 @@ func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleG
 // On success, EditBuildList reports whether the selected version of any module
 // in the build list may have been changed (possibly to or from "none") as a
 // result.
-func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) {
-       rs, changed, err := editRequirements(ctx, LoadModFile(ctx), add, mustSelect)
+func EditBuildList(loaderstate *State, ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) {
+       rs, changed, err := editRequirements(loaderstate, ctx, LoadModFile(loaderstate, ctx), add, mustSelect)
        if err != nil {
                return false, err
        }
-       LoaderState.requirements = rs
+       loaderstate.requirements = rs
        return changed, nil
 }
 
-func overrideRoots(ctx context.Context, rs *Requirements, replace []module.Version) *Requirements {
+func overrideRoots(loaderstate *State, ctx context.Context, rs *Requirements, replace []module.Version) *Requirements {
        drop := make(map[string]bool)
        for _, m := range replace {
                drop[m.Path] = true
@@ -661,7 +661,7 @@ func overrideRoots(ctx context.Context, rs *Requirements, replace []module.Versi
        }
        roots = append(roots, replace...)
        gover.ModSort(roots)
-       return newRequirements(rs.pruning, roots, rs.direct)
+       return newRequirements(loaderstate, rs.pruning, roots, rs.direct)
 }
 
 // A ConstraintError describes inconsistent constraints in EditBuildList
@@ -765,28 +765,28 @@ func (c Conflict) String() string {
 // tidyRoots trims the root dependencies to the minimal requirements needed to
 // both retain the same versions of all packages in pkgs and satisfy the
 // graph-pruning invariants (if applicable).
-func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) {
-       mainModule := LoaderState.MainModules.mustGetSingleMainModule()
+func tidyRoots(loaderstate *State, ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) {
+       mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate)
        if rs.pruning == unpruned {
-               return tidyUnprunedRoots(ctx, mainModule, rs, pkgs)
+               return tidyUnprunedRoots(loaderstate, ctx, mainModule, rs, pkgs)
        }
-       return tidyPrunedRoots(ctx, mainModule, rs, pkgs)
+       return tidyPrunedRoots(loaderstate, ctx, mainModule, rs, pkgs)
 }
 
-func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
+func updateRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
        switch rs.pruning {
        case unpruned:
-               return updateUnprunedRoots(ctx, direct, rs, add)
+               return updateUnprunedRoots(loaderstate, ctx, direct, rs, add)
        case pruned:
-               return updatePrunedRoots(ctx, direct, rs, pkgs, add, rootsImported)
+               return updatePrunedRoots(loaderstate, ctx, direct, rs, pkgs, add, rootsImported)
        case workspace:
-               return updateWorkspaceRoots(ctx, direct, rs, add)
+               return updateWorkspaceRoots(loaderstate, ctx, direct, rs, add)
        default:
                panic(fmt.Sprintf("unsupported pruning mode: %v", rs.pruning))
        }
 }
 
-func updateWorkspaceRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) {
+func updateWorkspaceRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) {
        if len(add) != 0 {
                // add should be empty in workspace mode because workspace mode implies
                // -mod=readonly, which in turn implies no new requirements. The code path
@@ -797,7 +797,7 @@ func updateWorkspaceRoots(ctx context.Context, direct map[string]bool, rs *Requi
                // return an error.
                panic("add is not empty")
        }
-       return newRequirements(workspace, rs.rootModules, direct), nil
+       return newRequirements(loaderstate, workspace, rs.rootModules, direct), nil
 }
 
 // tidyPrunedRoots returns a minimal set of root requirements that maintains the
@@ -816,16 +816,16 @@ func updateWorkspaceRoots(ctx context.Context, direct map[string]bool, rs *Requi
 // To ensure that the loading process eventually converges, the caller should
 // add any needed roots from the tidy root set (without removing existing untidy
 // roots) until the set of roots has converged.
-func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) {
+func tidyPrunedRoots(loaderstate *State, ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) {
        var (
                roots      []module.Version
                pathIsRoot = map[string]bool{mainModule.Path: true}
        )
-       if v, ok := old.rootSelected("go"); ok {
+       if v, ok := old.rootSelected(loaderstate, "go"); ok {
                roots = append(roots, module.Version{Path: "go", Version: v})
                pathIsRoot["go"] = true
        }
-       if v, ok := old.rootSelected("toolchain"); ok {
+       if v, ok := old.rootSelected(loaderstate, "toolchain"); ok {
                roots = append(roots, module.Version{Path: "toolchain", Version: v})
                pathIsRoot["toolchain"] = true
        }
@@ -847,7 +847,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir
                if !pkg.flags.has(pkgInAll) {
                        continue
                }
-               if pkg.fromExternalModule() && !pathIsRoot[pkg.mod.Path] {
+               if pkg.fromExternalModule(loaderstate) && !pathIsRoot[pkg.mod.Path] {
                        roots = append(roots, pkg.mod)
                        pathIsRoot[pkg.mod.Path] = true
                }
@@ -855,11 +855,11 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir
                queued[pkg] = true
        }
        gover.ModSort(roots)
-       tidy := newRequirements(pruned, roots, old.direct)
+       tidy := newRequirements(loaderstate, pruned, roots, old.direct)
 
        for len(queue) > 0 {
                roots = tidy.rootModules
-               mg, err := tidy.Graph(ctx)
+               mg, err := tidy.Graph(loaderstate, ctx)
                if err != nil {
                        return nil, err
                }
@@ -892,12 +892,12 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir
 
                if len(roots) > len(tidy.rootModules) {
                        gover.ModSort(roots)
-                       tidy = newRequirements(pruned, roots, tidy.direct)
+                       tidy = newRequirements(loaderstate, pruned, roots, tidy.direct)
                }
        }
 
        roots = tidy.rootModules
-       _, err := tidy.Graph(ctx)
+       _, err := tidy.Graph(loaderstate, ctx)
        if err != nil {
                return nil, err
        }
@@ -921,7 +921,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir
                        pkg := pkg
                        q.Add(func() {
                                skipModFile := true
-                               _, _, _, _, err := importFromModules(ctx, pkg.path, tidy, nil, skipModFile)
+                               _, _, _, _, err := importFromModules(loaderstate, ctx, pkg.path, tidy, nil, skipModFile)
                                if _, ok := errors.AsType[*AmbiguousImportError](err); ok {
                                        disambiguateRoot.Store(pkg.mod, true)
                                }
@@ -938,8 +938,8 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir
 
                if len(roots) > len(tidy.rootModules) {
                        module.Sort(roots)
-                       tidy = newRequirements(pruned, roots, tidy.direct)
-                       _, err = tidy.Graph(ctx)
+                       tidy = newRequirements(loaderstate, pruned, roots, tidy.direct)
+                       _, err = tidy.Graph(loaderstate, ctx)
                        if err != nil {
                                return nil, err
                        }
@@ -999,7 +999,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir
 //
 // (See https://golang.org/design/36460-lazy-module-loading#invariants for more
 // detail.)
-func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
+func updatePrunedRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
        roots := rs.rootModules
        rootsUpgraded := false
 
@@ -1009,7 +1009,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
        // either pkgInAll or pkgIsRoot is included as a root.”
        needSort := false
        for _, pkg := range pkgs {
-               if !pkg.fromExternalModule() {
+               if !pkg.fromExternalModule(loaderstate) {
                        // pkg was not loaded from a module dependency, so we don't need
                        // to do anything special to maintain that dependency.
                        continue
@@ -1058,7 +1058,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
                        continue
                }
 
-               if _, ok := rs.rootSelected(pkg.mod.Path); ok {
+               if _, ok := rs.rootSelected(loaderstate, pkg.mod.Path); ok {
                        // It is possible that the main module's go.mod file is incomplete or
                        // otherwise erroneous — for example, perhaps the author forgot to 'git
                        // add' their updated go.mod file after adding a new package import, or
@@ -1094,7 +1094,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
        }
 
        for _, m := range add {
-               if v, ok := rs.rootSelected(m.Path); !ok || gover.ModCompare(m.Path, v, m.Version) < 0 {
+               if v, ok := rs.rootSelected(loaderstate, m.Path); !ok || gover.ModCompare(m.Path, v, m.Version) < 0 {
                        roots = append(roots, m)
                        rootsUpgraded = true
                        needSort = true
@@ -1111,7 +1111,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
                        // We've added or upgraded one or more roots, so load the full module
                        // graph so that we can update those roots to be consistent with other
                        // requirements.
-                       if mustHaveCompleteRequirements() {
+                       if mustHaveCompleteRequirements(loaderstate) {
                                // Our changes to the roots may have moved dependencies into or out of
                                // the graph-pruning horizon, which could in turn change the selected
                                // versions of other modules. (For pruned modules adding or removing an
@@ -1119,9 +1119,9 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
                                return rs, errGoModDirty
                        }
 
-                       rs = newRequirements(pruned, roots, direct)
+                       rs = newRequirements(loaderstate, pruned, roots, direct)
                        var err error
-                       mg, err = rs.Graph(ctx)
+                       mg, err = rs.Graph(loaderstate, ctx)
                        if err != nil {
                                return rs, err
                        }
@@ -1135,20 +1135,20 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
                                // We've already loaded the full module graph, which includes the
                                // requirements of all of the root modules — even the transitive
                                // requirements, if they are unpruned!
-                               mg, _ = rs.Graph(ctx)
+                               mg, _ = rs.Graph(loaderstate, ctx)
                        } else if cfg.BuildMod == "vendor" {
                                // We can't spot-check the requirements of other modules because we
                                // don't in general have their go.mod files available in the vendor
                                // directory. (Fortunately this case is impossible, because mg.graph is
                                // always non-nil in vendor mode!)
                                panic("internal error: rs.graph is unexpectedly nil with -mod=vendor")
-                       } else if !spotCheckRoots(ctx, rs, spotCheckRoot) {
+                       } else if !spotCheckRoots(loaderstate, ctx, rs, spotCheckRoot) {
                                // We spot-checked the explicit requirements of the roots that are
                                // relevant to the packages we've loaded. Unfortunately, they're
                                // inconsistent in some way; we need to load the full module graph
                                // so that we can fix the roots properly.
                                var err error
-                               mg, err = rs.Graph(ctx)
+                               mg, err = rs.Graph(loaderstate, ctx)
                                if err != nil {
                                        return rs, err
                                }
@@ -1158,7 +1158,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
                roots = make([]module.Version, 0, len(rs.rootModules))
                rootsUpgraded = false
                inRootPaths := make(map[string]bool, len(rs.rootModules)+1)
-               for _, mm := range LoaderState.MainModules.Versions() {
+               for _, mm := range loaderstate.MainModules.Versions() {
                        inRootPaths[mm.Path] = true
                }
                for _, m := range rs.rootModules {
@@ -1184,7 +1184,7 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
 
                        var v string
                        if mg == nil {
-                               v, _ = rs.rootSelected(m.Path)
+                               v, _ = rs.rootSelected(loaderstate, m.Path)
                        } else {
                                v = mg.Selected(m.Path)
                        }
@@ -1218,12 +1218,12 @@ func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirem
                // preserve its cached ModuleGraph (if any).
                return rs, nil
        }
-       return newRequirements(pruned, roots, direct), nil
+       return newRequirements(loaderstate, pruned, roots, direct), nil
 }
 
 // spotCheckRoots reports whether the versions of the roots in rs satisfy the
 // explicit requirements of the modules in mods.
-func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Version]bool) bool {
+func spotCheckRoots(loaderstate *State, ctx context.Context, rs *Requirements, mods map[module.Version]bool) bool {
        ctx, cancel := context.WithCancel(ctx)
        defer cancel()
 
@@ -1235,14 +1235,14 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi
                                return
                        }
 
-                       summary, err := goModSummary(m)
+                       summary, err := goModSummary(loaderstate, m)
                        if err != nil {
                                cancel()
                                return
                        }
 
                        for _, r := range summary.require {
-                               if v, ok := rs.rootSelected(r.Path); ok && gover.ModCompare(r.Path, v, r.Version) < 0 {
+                               if v, ok := rs.rootSelected(loaderstate, r.Path); ok && gover.ModCompare(r.Path, v, r.Version) < 0 {
                                        cancel()
                                        return
                                }
@@ -1264,7 +1264,7 @@ func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Versi
 // the selected version of every module that provided or lexically could have
 // provided a package in pkgs, and includes the selected version of every such
 // module in direct as a root.
-func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) {
+func tidyUnprunedRoots(loaderstate *State, ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) {
        var (
                // keep is a set of modules that provide packages or are needed to
                // disambiguate imports.
@@ -1292,16 +1292,16 @@ func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requ
                // without its sum. See #47738.
                altMods = map[string]string{}
        )
-       if v, ok := old.rootSelected("go"); ok {
+       if v, ok := old.rootSelected(loaderstate, "go"); ok {
                keep = append(keep, module.Version{Path: "go", Version: v})
                keptPath["go"] = true
        }
-       if v, ok := old.rootSelected("toolchain"); ok {
+       if v, ok := old.rootSelected(loaderstate, "toolchain"); ok {
                keep = append(keep, module.Version{Path: "toolchain", Version: v})
                keptPath["toolchain"] = true
        }
        for _, pkg := range pkgs {
-               if !pkg.fromExternalModule() {
+               if !pkg.fromExternalModule(loaderstate) {
                        continue
                }
                if m := pkg.mod; !keptPath[m.Path] {
@@ -1350,7 +1350,7 @@ func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requ
                }
        }
 
-       return newRequirements(unpruned, min, old.direct), nil
+       return newRequirements(loaderstate, unpruned, min, old.direct), nil
 }
 
 // updateUnprunedRoots returns a set of root requirements that includes the selected
@@ -1367,8 +1367,8 @@ func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requ
 //     by a dependency in add.
 //  4. Every version in add is selected at its given version unless upgraded by
 //     (the dependencies of) an existing root or another module in add.
-func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) {
-       mg, err := rs.Graph(ctx)
+func updateUnprunedRoots(loaderstate *State, ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) {
+       mg, err := rs.Graph(loaderstate, ctx)
        if err != nil {
                // We can't ignore errors in the module graph even if the user passed the -e
                // flag to try to push past them. If we can't load the complete module
@@ -1376,7 +1376,7 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir
                return rs, err
        }
 
-       if mustHaveCompleteRequirements() {
+       if mustHaveCompleteRequirements(loaderstate) {
                // Instead of actually updating the requirements, just check that no updates
                // are needed.
                if rs == nil {
@@ -1396,7 +1396,7 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir
                        }
                }
                for mPath := range direct {
-                       if _, ok := rs.rootSelected(mPath); !ok {
+                       if _, ok := rs.rootSelected(loaderstate, mPath); !ok {
                                // Module m is supposed to be listed explicitly, but isn't.
                                //
                                // Note that this condition is also detected (and logged with more
@@ -1435,7 +1435,7 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir
        // This is only for convenience and clarity for end users: in an unpruned module,
        // the choice of explicit vs. implicit dependency has no impact on MVS
        // selection (for itself or any other module).
-       keep := append(mg.BuildList()[LoaderState.MainModules.Len():], add...)
+       keep := append(mg.BuildList()[loaderstate.MainModules.Len():], add...)
        for _, m := range keep {
                if direct[m.Path] && !inRootPaths[m.Path] {
                        rootPaths = append(rootPaths, m.Path)
@@ -1444,14 +1444,14 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir
        }
 
        var roots []module.Version
-       for _, mainModule := range LoaderState.MainModules.Versions() {
+       for _, mainModule := range loaderstate.MainModules.Versions() {
                min, err := mvs.Req(mainModule, rootPaths, &mvsReqs{roots: keep})
                if err != nil {
                        return rs, err
                }
                roots = append(roots, min...)
        }
-       if LoaderState.MainModules.Len() > 1 {
+       if loaderstate.MainModules.Len() > 1 {
                gover.ModSort(roots)
        }
        if rs.pruning == unpruned && slices.Equal(roots, rs.rootModules) && maps.Equal(direct, rs.direct) {
@@ -1460,12 +1460,12 @@ func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requir
                return rs, nil
        }
 
-       return newRequirements(unpruned, roots, direct), nil
+       return newRequirements(loaderstate, unpruned, roots, direct), nil
 }
 
 // convertPruning returns a version of rs with the given pruning behavior.
 // If rs already has the given pruning, convertPruning returns rs unmodified.
-func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) {
+func convertPruning(loaderstate *State, ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) {
        if rs.pruning == pruning {
                return rs, nil
        } else if rs.pruning == workspace || pruning == workspace {
@@ -1477,7 +1477,7 @@ func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (
                // pruned module graph are a superset of the roots of an unpruned one, so
                // we don't need to add any new roots — we just need to drop the ones that
                // are redundant, which is exactly what updateUnprunedRoots does.
-               return updateUnprunedRoots(ctx, rs.direct, rs, nil)
+               return updateUnprunedRoots(loaderstate, ctx, rs.direct, rs, nil)
        }
 
        // We are converting an unpruned module to a pruned one.
@@ -1487,9 +1487,9 @@ func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (
        // root set! “Include the transitive dependencies of every module in the build
        // list” is exactly what happens in a pruned module if we promote every module
        // in the build list to a root.
-       mg, err := rs.Graph(ctx)
+       mg, err := rs.Graph(loaderstate, ctx)
        if err != nil {
                return rs, err
        }
-       return newRequirements(pruned, mg.BuildList()[LoaderState.MainModules.Len():], rs.direct), nil
+       return newRequirements(loaderstate, pruned, mg.BuildList()[loaderstate.MainModules.Len():], rs.direct), nil
 }
index 96d864545d042afac3e9fd7ef4ee0bd4de0e0eb1..72d0f754224456789742745ab52e538d58ac7d4c 100644 (file)
@@ -42,7 +42,7 @@ import (
 // If pruning is enabled, the roots of the edited requirements include an
 // explicit entry for each module path in tryUpgrade, mustSelect, and the roots
 // of rs, unless the selected version for the module path is "none".
-func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (edited *Requirements, changed bool, err error) {
+func editRequirements(loaderstate *State, ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (edited *Requirements, changed bool, err error) {
        if rs.pruning == workspace {
                panic("editRequirements cannot edit workspace requirements")
        }
@@ -82,7 +82,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
        }
 
        if rootPruning != rs.pruning {
-               rs, err = convertPruning(ctx, rs, rootPruning)
+               rs, err = convertPruning(loaderstate, ctx, rs, rootPruning)
                if err != nil {
                        return orig, false, err
                }
@@ -100,13 +100,13 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
                // dependencies, so we need to treat everything in the build list as
                // potentially relevant — that is, as what would be a “root” in a module
                // with graph pruning enabled.
-               mg, err := rs.Graph(ctx)
+               mg, err := rs.Graph(loaderstate, ctx)
                if err != nil {
                        // If we couldn't load the graph, we don't know what its requirements were
                        // to begin with, so we can't edit those requirements in a coherent way.
                        return orig, false, err
                }
-               bl := mg.BuildList()[LoaderState.MainModules.Len():]
+               bl := mg.BuildList()[loaderstate.MainModules.Len():]
                selectedRoot = make(map[string]string, len(bl))
                for _, m := range bl {
                        selectedRoot[m.Path] = m.Version
@@ -224,7 +224,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
                // of every root. The upgraded roots are in addition to the original
                // roots, so we will have enough information to trace a path to each
                // conflict we discover from one or more of the original roots.
-               mg, upgradedRoots, err := extendGraph(ctx, rootPruning, roots, selectedRoot)
+               mg, upgradedRoots, err := extendGraph(loaderstate, ctx, rootPruning, roots, selectedRoot)
                if err != nil {
                        if mg == nil {
                                return orig, false, err
@@ -391,7 +391,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
                        // the edit. We want to make sure we consider keeping it as-is,
                        // even if it wouldn't normally be included. (For example, it might
                        // be a pseudo-version or pre-release.)
-                       origMG, _ := orig.Graph(ctx)
+                       origMG, _ := orig.Graph(loaderstate, ctx)
                        origV := origMG.Selected(m.Path)
 
                        if conflict.Err != nil && origV == m.Version {
@@ -415,7 +415,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
                        rejectedRoot[m] = true
                        prev := m
                        for {
-                               prev, err = previousVersion(ctx, prev)
+                               prev, err = previousVersion(loaderstate, ctx, prev)
                                if gover.ModCompare(m.Path, m.Version, origV) > 0 && (gover.ModCompare(m.Path, prev.Version, origV) < 0 || err != nil) {
                                        // previousVersion skipped over origV. Insert it into the order.
                                        prev.Version = origV
@@ -515,13 +515,13 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
 
                // The modules in mustSelect are always promoted to be explicit.
                for _, m := range mustSelect {
-                       if m.Version != "none" && !LoaderState.MainModules.Contains(m.Path) {
+                       if m.Version != "none" && !loaderstate.MainModules.Contains(m.Path) {
                                rootPaths = append(rootPaths, m.Path)
                        }
                }
 
                for _, m := range roots {
-                       if v, ok := rs.rootSelected(m.Path); ok && (v == m.Version || rs.direct[m.Path]) {
+                       if v, ok := rs.rootSelected(loaderstate, m.Path); ok && (v == m.Version || rs.direct[m.Path]) {
                                // m.Path was formerly a root, and either its version hasn't changed or
                                // we believe that it provides a package directly imported by a package
                                // or test in the main module. For now we'll assume that it is still
@@ -532,7 +532,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
                        }
                }
 
-               roots, err = mvs.Req(LoaderState.MainModules.mustGetSingleMainModule(), rootPaths, &mvsReqs{roots: roots})
+               roots, err = mvs.Req(loaderstate.MainModules.mustGetSingleMainModule(loaderstate), rootPaths, &mvsReqs{roots: roots})
                if err != nil {
                        return nil, false, err
                }
@@ -563,7 +563,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
                        direct[m.Path] = true
                }
        }
-       edited = newRequirements(rootPruning, roots, direct)
+       edited = newRequirements(loaderstate, rootPruning, roots, direct)
 
        // If we ended up adding a dependency that upgrades our go version far enough
        // to activate pruning, we must convert the edited Requirements in order to
@@ -578,7 +578,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
        // those two modules will never be downgraded due to a conflict with any other
        // constraint.
        if rootPruning == unpruned {
-               if v, ok := edited.rootSelected("go"); ok && pruningForGoVersion(v) == pruned {
+               if v, ok := edited.rootSelected(loaderstate, "go"); ok && pruningForGoVersion(v) == pruned {
                        // Since we computed the edit with the unpruned graph, and the pruned
                        // graph is a strict subset of the unpruned graph, this conversion
                        // preserves the exact (edited) build list that we already computed.
@@ -587,7 +587,7 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
                        // the graph. 'go get' will check for that sort of transition and log a
                        // message reminding the user how to clean up this mess we're about to
                        // make. 😅
-                       edited, err = convertPruning(ctx, edited, pruned)
+                       edited, err = convertPruning(loaderstate, ctx, edited, pruned)
                        if err != nil {
                                return orig, false, err
                        }
@@ -607,9 +607,9 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
 // The extended graph is useful for diagnosing version conflicts: for each
 // selected module version, it can provide a complete path of requirements from
 // some root to that version.
-func extendGraph(ctx context.Context, rootPruning modPruning, roots []module.Version, selectedRoot map[string]string) (mg *ModuleGraph, upgradedRoot map[module.Version]bool, err error) {
+func extendGraph(loaderstate *State, ctx context.Context, rootPruning modPruning, roots []module.Version, selectedRoot map[string]string) (mg *ModuleGraph, upgradedRoot map[module.Version]bool, err error) {
        for {
-               mg, err = readModGraph(ctx, rootPruning, roots, upgradedRoot)
+               mg, err = readModGraph(loaderstate, ctx, rootPruning, roots, upgradedRoot)
                // We keep on going even if err is non-nil until we reach a steady state.
                // (Note that readModGraph returns a non-nil *ModuleGraph even in case of
                // errors.) The caller may be able to fix the errors by adjusting versions,
index 392fe3edd77b52c0049ec93d42c4c0c33421c2aa..a2a98289b0ed77cfdb8d1c139de5ed81f94467f2 100644 (file)
@@ -262,7 +262,7 @@ func (e *invalidImportError) Unwrap() error {
 // (https://go.dev/issue/56222) for modules with 'go' versions between 1.17 and
 // 1.20, preventing unnecessary go.sum churn and network access in those
 // modules.
-func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph, skipModFile bool) (m module.Version, modroot, dir string, altMods []module.Version, err error) {
+func importFromModules(loaderstate *State, ctx context.Context, path string, rs *Requirements, mg *ModuleGraph, skipModFile bool) (m module.Version, modroot, dir string, altMods []module.Version, err error) {
        invalidf := func(format string, args ...interface{}) (module.Version, string, string, []module.Version, error) {
                return module.Version{}, "", "", nil, &invalidImportError{
                        importPath: path,
@@ -299,12 +299,12 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
        // Is the package in the standard library?
        pathIsStd := search.IsStandardImportPath(path)
        if pathIsStd && modindex.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
-               for _, mainModule := range LoaderState.MainModules.Versions() {
-                       if LoaderState.MainModules.InGorootSrc(mainModule) {
-                               if dir, ok, err := dirInModule(path, LoaderState.MainModules.PathPrefix(mainModule), LoaderState.MainModules.ModRoot(mainModule), true); err != nil {
-                                       return module.Version{}, LoaderState.MainModules.ModRoot(mainModule), dir, nil, err
+               for _, mainModule := range loaderstate.MainModules.Versions() {
+                       if loaderstate.MainModules.InGorootSrc(mainModule) {
+                               if dir, ok, err := dirInModule(path, loaderstate.MainModules.PathPrefix(mainModule), loaderstate.MainModules.ModRoot(mainModule), true); err != nil {
+                                       return module.Version{}, loaderstate.MainModules.ModRoot(mainModule), dir, nil, err
                                } else if ok {
-                                       return mainModule, LoaderState.MainModules.ModRoot(mainModule), dir, nil, nil
+                                       return mainModule, loaderstate.MainModules.ModRoot(mainModule), dir, nil, nil
                                }
                        }
                }
@@ -321,10 +321,10 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
        // Everything must be in the main modules or the main module's or workspace's vendor directory.
        if cfg.BuildMod == "vendor" {
                var mainErr error
-               for _, mainModule := range LoaderState.MainModules.Versions() {
-                       modRoot := LoaderState.MainModules.ModRoot(mainModule)
+               for _, mainModule := range loaderstate.MainModules.Versions() {
+                       modRoot := loaderstate.MainModules.ModRoot(mainModule)
                        if modRoot != "" {
-                               dir, mainOK, err := dirInModule(path, LoaderState.MainModules.PathPrefix(mainModule), modRoot, true)
+                               dir, mainOK, err := dirInModule(path, loaderstate.MainModules.PathPrefix(mainModule), modRoot, true)
                                if mainErr == nil {
                                        mainErr = err
                                }
@@ -336,8 +336,8 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
                        }
                }
 
-               if HasModRoot() {
-                       vendorDir := VendorDir()
+               if HasModRoot(loaderstate) {
+                       vendorDir := VendorDir(loaderstate)
                        dir, inVendorDir, _ := dirInModule(path, "", vendorDir, false)
                        if inVendorDir {
                                readVendorList(vendorDir)
@@ -345,13 +345,13 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
                                // vendor/modules.txt does not exist or the user manually added directories to the vendor directory.
                                // Go 1.23 and later require vendored packages to be present in modules.txt to be imported.
                                _, ok := vendorPkgModule[path]
-                               if ok || (gover.Compare(LoaderState.MainModules.GoVersion(), gover.ExplicitModulesTxtImportVersion) < 0) {
+                               if ok || (gover.Compare(loaderstate.MainModules.GoVersion(loaderstate), gover.ExplicitModulesTxtImportVersion) < 0) {
                                        mods = append(mods, vendorPkgModule[path])
                                        dirs = append(dirs, dir)
                                        roots = append(roots, vendorDir)
                                } else {
                                        subCommand := "mod"
-                                       if inWorkspaceMode() {
+                                       if inWorkspaceMode(loaderstate) {
                                                subCommand = "work"
                                        }
                                        fmt.Fprintf(os.Stderr, "go: ignoring package %s which exists in the vendor directory but is missing from vendor/modules.txt. To sync the vendor directory run go %s vendor.\n", path, subCommand)
@@ -399,7 +399,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
                                ok bool
                        )
                        if mg == nil {
-                               v, ok = rs.rootSelected(prefix)
+                               v, ok = rs.rootSelected(loaderstate, prefix)
                        } else {
                                v, ok = mg.Selected(prefix), true
                        }
@@ -408,7 +408,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
                        }
                        m := module.Version{Path: prefix, Version: v}
 
-                       root, isLocal, err := fetch(ctx, m)
+                       root, isLocal, err := fetch(loaderstate, ctx, m)
                        if err != nil {
                                if _, ok := errors.AsType[*sumMissingError](err); ok {
                                        // We are missing a sum needed to fetch a module in the build list.
@@ -471,8 +471,8 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
                        // If the module graph is pruned and this is a test-only dependency
                        // of a package in "all", we didn't necessarily load that file
                        // when we read the module graph, so do it now to be sure.
-                       if !skipModFile && cfg.BuildMod != "vendor" && mods[0].Path != "" && !LoaderState.MainModules.Contains(mods[0].Path) {
-                               if _, err := goModSummary(mods[0]); err != nil {
+                       if !skipModFile && cfg.BuildMod != "vendor" && mods[0].Path != "" && !loaderstate.MainModules.Contains(mods[0].Path) {
+                               if _, err := goModSummary(loaderstate, mods[0]); err != nil {
                                        return module.Version{}, "", "", nil, err
                                }
                        }
@@ -483,7 +483,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
                        // We checked the full module graph and still didn't find the
                        // requested package.
                        var queryErr error
-                       if !HasModRoot() {
+                       if !HasModRoot(loaderstate) {
                                queryErr = ErrNoModRoot
                        }
                        return module.Version{}, "", "", nil, &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd}
@@ -491,7 +491,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
 
                // So far we've checked the root dependencies.
                // Load the full module graph and try again.
-               mg, err = rs.Graph(ctx)
+               mg, err = rs.Graph(loaderstate, ctx)
                if err != nil {
                        // We might be missing one or more transitive (implicit) dependencies from
                        // the module graph, so we can't return an ImportMissingError here — one
@@ -507,12 +507,12 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
 //
 // Unlike QueryPattern, queryImport prefers to add a replaced version of a
 // module *before* checking the proxies for a version to add.
-func queryImport(ctx context.Context, path string, rs *Requirements) (module.Version, error) {
+func queryImport(loaderstate *State, ctx context.Context, path string, rs *Requirements) (module.Version, error) {
        // To avoid spurious remote fetches, try the latest replacement for each
        // module (golang.org/issue/26241).
        var mods []module.Version
-       if LoaderState.MainModules != nil { // TODO(#48912): Ensure MainModules exists at this point, and remove the check.
-               for mp, mv := range LoaderState.MainModules.HighestReplaced() {
+       if loaderstate.MainModules != nil { // TODO(#48912): Ensure MainModules exists at this point, and remove the check.
+               for mp, mv := range loaderstate.MainModules.HighestReplaced() {
                        if !maybeInModule(path, mp) {
                                continue
                        }
@@ -528,7 +528,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver
                                        mv = module.ZeroPseudoVersion("v0")
                                }
                        }
-                       mg, err := rs.Graph(ctx)
+                       mg, err := rs.Graph(loaderstate, ctx)
                        if err != nil {
                                return module.Version{}, err
                        }
@@ -547,7 +547,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver
                return len(mods[i].Path) > len(mods[j].Path)
        })
        for _, m := range mods {
-               root, isLocal, err := fetch(ctx, m)
+               root, isLocal, err := fetch(loaderstate, ctx, m)
                if err != nil {
                        if _, ok := errors.AsType[*sumMissingError](err); ok {
                                return module.Version{}, &ImportMissingSumError{importPath: path}
@@ -567,7 +567,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver
                // The package path is not valid to fetch remotely,
                // so it can only exist in a replaced module,
                // and we know from the above loop that it is not.
-               replacement := Replacement(mods[0])
+               replacement := Replacement(loaderstate, mods[0])
                return module.Version{}, &PackageNotInModuleError{
                        Mod:         mods[0],
                        Query:       "latest",
@@ -607,12 +607,12 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver
        // and return m, dir, ImportMissingError.
        fmt.Fprintf(os.Stderr, "go: finding module for package %s\n", path)
 
-       mg, err := rs.Graph(ctx)
+       mg, err := rs.Graph(loaderstate, ctx)
        if err != nil {
                return module.Version{}, err
        }
 
-       candidates, err := QueryPackages(ctx, path, "latest", mg.Selected, CheckAllowed)
+       candidates, err := QueryPackages(loaderstate, ctx, path, "latest", mg.Selected, CheckAllowed)
        if err != nil {
                if errors.Is(err, fs.ErrNotExist) {
                        // Return "cannot find module providing package […]" instead of whatever
@@ -747,15 +747,15 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
 //
 // The isLocal return value reports whether the replacement,
 // if any, is local to the filesystem.
-func fetch(ctx context.Context, mod module.Version) (dir string, isLocal bool, err error) {
-       if modRoot := LoaderState.MainModules.ModRoot(mod); modRoot != "" {
+func fetch(loaderstate *State, ctx context.Context, mod module.Version) (dir string, isLocal bool, err error) {
+       if modRoot := loaderstate.MainModules.ModRoot(mod); modRoot != "" {
                return modRoot, true, nil
        }
-       if r := Replacement(mod); r.Path != "" {
+       if r := Replacement(loaderstate, mod); r.Path != "" {
                if r.Version == "" {
                        dir = r.Path
                        if !filepath.IsAbs(dir) {
-                               dir = filepath.Join(replaceRelativeTo(), dir)
+                               dir = filepath.Join(replaceRelativeTo(loaderstate), dir)
                        }
                        // Ensure that the replacement directory actually exists:
                        // dirInModule does not report errors for missing modules,
@@ -780,7 +780,7 @@ func fetch(ctx context.Context, mod module.Version) (dir string, isLocal bool, e
                mod = r
        }
 
-       if mustHaveSums() && !modfetch.HaveSum(mod) {
+       if mustHaveSums(loaderstate) && !modfetch.HaveSum(mod) {
                return "", false, module.VersionError(mod, &sumMissingError{})
        }
 
@@ -790,8 +790,8 @@ func fetch(ctx context.Context, mod module.Version) (dir string, isLocal bool, e
 
 // mustHaveSums reports whether we require that all checksums
 // needed to load or build packages are already present in the go.sum file.
-func mustHaveSums() bool {
-       return HasModRoot() && cfg.BuildMod == "readonly" && !inWorkspaceMode()
+func mustHaveSums(loaderstate *State) bool {
+       return HasModRoot(loaderstate) && cfg.BuildMod == "readonly" && !inWorkspaceMode(loaderstate)
 }
 
 type sumMissingError struct {
index f6b8bb90992735188a13be51eed593f3f3d0524f..a5c4b837a0be12192f03ffdc8b5ca5cda4e084f6 100644 (file)
@@ -69,12 +69,12 @@ func TestQueryImport(t *testing.T) {
        LoaderState.RootMode = NoRoot
 
        ctx := context.Background()
-       rs := LoadModFile(ctx)
+       rs := LoadModFile(LoaderState, ctx)
 
        for _, tt := range importTests {
                t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
                        // Note that there is no build list, so Import should always fail.
-                       m, err := queryImport(ctx, tt.path, rs)
+                       m, err := queryImport(LoaderState, ctx, tt.path, rs)
 
                        if tt.err == "" {
                                if err != nil {
index 31fe6327735736dd0e13a5cbc2704f76cc23d49e..20751528862ce268bf2e9df05cf1190cc81d013e 100644 (file)
@@ -64,7 +64,7 @@ func EnterModule(ctx context.Context, enterModroot string) {
        modfetch.Reset()
 
        LoaderState.modRoots = []string{enterModroot}
-       LoadModFile(ctx)
+       LoadModFile(LoaderState, ctx)
 }
 
 // EnterWorkspace enters workspace mode from module mode, applying the updated requirements to the main
@@ -73,9 +73,9 @@ func EnterModule(ctx context.Context, enterModroot string) {
 // EnterWorkspace will modify the global state they depend on in a non-thread-safe way.
 func EnterWorkspace(ctx context.Context) (exit func(), err error) {
        // Find the identity of the main module that will be updated before we reset modload state.
-       mm := LoaderState.MainModules.mustGetSingleMainModule()
+       mm := LoaderState.MainModules.mustGetSingleMainModule(LoaderState)
        // Get the updated modfile we will use for that module.
-       _, _, updatedmodfile, err := UpdateGoModFromReqs(ctx, WriteOpts{})
+       _, _, updatedmodfile, err := UpdateGoModFromReqs(LoaderState, ctx, WriteOpts{})
        if err != nil {
                return nil, err
        }
@@ -85,12 +85,12 @@ func EnterWorkspace(ctx context.Context) (exit func(), err error) {
        LoaderState.ForceUseModules = true
 
        // Load in workspace mode.
-       InitWorkfile()
-       LoadModFile(ctx)
+       InitWorkfile(LoaderState)
+       LoadModFile(LoaderState, ctx)
 
        // Update the content of the previous main module, and recompute the requirements.
        *LoaderState.MainModules.ModFile(mm) = *updatedmodfile
-       LoaderState.requirements = requirementsFromModFiles(ctx, LoaderState.MainModules.workFile, slices.Collect(maps.Values(LoaderState.MainModules.modFiles)), nil)
+       LoaderState.requirements = requirementsFromModFiles(LoaderState, ctx, LoaderState.MainModules.workFile, slices.Collect(maps.Values(LoaderState.MainModules.modFiles)), nil)
 
        return func() {
                setState(oldstate)
@@ -182,12 +182,12 @@ func (mms *MainModuleSet) InGorootSrc(m module.Version) bool {
        return mms.inGorootSrc[m]
 }
 
-func (mms *MainModuleSet) mustGetSingleMainModule() module.Version {
+func (mms *MainModuleSet) mustGetSingleMainModule(loaderstate *State) module.Version {
        if mms == nil || len(mms.versions) == 0 {
                panic("internal error: mustGetSingleMainModule called in context with no main modules")
        }
        if len(mms.versions) != 1 {
-               if inWorkspaceMode() {
+               if inWorkspaceMode(loaderstate) {
                        panic("internal error: mustGetSingleMainModule called in workspace mode")
                } else {
                        panic("internal error: multiple main modules present outside of workspace mode")
@@ -196,14 +196,14 @@ func (mms *MainModuleSet) mustGetSingleMainModule() module.Version {
        return mms.versions[0]
 }
 
-func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex {
+func (mms *MainModuleSet) GetSingleIndexOrNil(loaderstate *State) *modFileIndex {
        if mms == nil {
                return nil
        }
        if len(mms.versions) == 0 {
                return nil
        }
-       return mms.indices[mms.mustGetSingleMainModule()]
+       return mms.indices[mms.mustGetSingleMainModule(loaderstate)]
 }
 
 func (mms *MainModuleSet) Index(m module.Version) *modFileIndex {
@@ -246,12 +246,12 @@ func (mms *MainModuleSet) HighestReplaced() map[string]string {
 
 // GoVersion returns the go version set on the single module, in module mode,
 // or the go.work file in workspace mode.
-func (mms *MainModuleSet) GoVersion() string {
-       if inWorkspaceMode() {
+func (mms *MainModuleSet) GoVersion(loaderstate *State) string {
+       if inWorkspaceMode(loaderstate) {
                return gover.FromGoWork(mms.workFile)
        }
        if mms != nil && len(mms.versions) == 1 {
-               f := mms.ModFile(mms.mustGetSingleMainModule())
+               f := mms.ModFile(mms.mustGetSingleMainModule(loaderstate))
                if f == nil {
                        // Special case: we are outside a module, like 'go run x.go'.
                        // Assume the local Go version.
@@ -266,15 +266,15 @@ func (mms *MainModuleSet) GoVersion() string {
 // Godebugs returns the godebug lines set on the single module, in module mode,
 // or on the go.work file in workspace mode.
 // The caller must not modify the result.
-func (mms *MainModuleSet) Godebugs() []*modfile.Godebug {
-       if inWorkspaceMode() {
+func (mms *MainModuleSet) Godebugs(loaderstate *State) []*modfile.Godebug {
+       if inWorkspaceMode(loaderstate) {
                if mms.workFile != nil {
                        return mms.workFile.Godebug
                }
                return nil
        }
        if mms != nil && len(mms.versions) == 1 {
-               f := mms.ModFile(mms.mustGetSingleMainModule())
+               f := mms.ModFile(mms.mustGetSingleMainModule(loaderstate))
                if f == nil {
                        // Special case: we are outside a module, like 'go run x.go'.
                        return nil
@@ -315,16 +315,16 @@ const (
 // To make permanent changes to the require statements
 // in go.mod, edit it before loading.
 func ModFile() *modfile.File {
-       Init()
-       modFile := LoaderState.MainModules.ModFile(LoaderState.MainModules.mustGetSingleMainModule())
+       Init(LoaderState)
+       modFile := LoaderState.MainModules.ModFile(LoaderState.MainModules.mustGetSingleMainModule(LoaderState))
        if modFile == nil {
-               die()
+               die(LoaderState)
        }
        return modFile
 }
 
-func BinDir() string {
-       Init()
+func BinDir(loaderstate *State) string {
+       Init(loaderstate)
        if cfg.GOBIN != "" {
                return cfg.GOBIN
        }
@@ -337,13 +337,13 @@ func BinDir() string {
 // InitWorkfile initializes the workFilePath variable for commands that
 // operate in workspace mode. It should not be called by other commands,
 // for example 'go mod tidy', that don't operate in workspace mode.
-func InitWorkfile() {
+func InitWorkfile(loaderstate *State) {
        // Initialize fsys early because we need overlay to read go.work file.
        fips140.Init()
        if err := fsys.Init(); err != nil {
                base.Fatal(err)
        }
-       LoaderState.workFilePath = FindGoWork(base.Cwd())
+       loaderstate.workFilePath = FindGoWork(loaderstate, base.Cwd())
 }
 
 // FindGoWork returns the name of the go.work file for this command,
@@ -351,8 +351,8 @@ func InitWorkfile() {
 // Most code should use Init and Enabled rather than use this directly.
 // It is exported mainly for Go toolchain switching, which must process
 // the go.work very early at startup.
-func FindGoWork(wd string) string {
-       if LoaderState.RootMode == NoRoot {
+func FindGoWork(loaderstate *State, wd string) string {
+       if loaderstate.RootMode == NoRoot {
                return ""
        }
 
@@ -371,8 +371,8 @@ func FindGoWork(wd string) string {
 
 // WorkFilePath returns the absolute path of the go.work file, or "" if not in
 // workspace mode. WorkFilePath must be called after InitWorkfile.
-func WorkFilePath() string {
-       return LoaderState.workFilePath
+func WorkFilePath(loaderstate *State) string {
+       return loaderstate.workFilePath
 }
 
 // Reset clears all the initialized, cached state about the use of modules,
@@ -451,11 +451,11 @@ var LoaderState = NewState()
 // current module (if any), sets environment variables for Git subprocesses, and
 // configures the cfg, codehost, load, modfetch, and search packages for use
 // with modules.
-func Init() {
-       if LoaderState.initialized {
+func Init(loaderstate *State) {
+       if loaderstate.initialized {
                return
        }
-       LoaderState.initialized = true
+       loaderstate.initialized = true
 
        fips140.Init()
 
@@ -468,11 +468,11 @@ func Init() {
        default:
                base.Fatalf("go: unknown environment setting GO111MODULE=%s", env)
        case "auto":
-               mustUseModules = LoaderState.ForceUseModules
+               mustUseModules = loaderstate.ForceUseModules
        case "on", "":
                mustUseModules = true
        case "off":
-               if LoaderState.ForceUseModules {
+               if loaderstate.ForceUseModules {
                        base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
                }
                mustUseModules = false
@@ -496,15 +496,15 @@ func Init() {
        if os.Getenv("GCM_INTERACTIVE") == "" {
                os.Setenv("GCM_INTERACTIVE", "never")
        }
-       if LoaderState.modRoots != nil {
+       if loaderstate.modRoots != nil {
                // modRoot set before Init was called ("go mod init" does this).
                // No need to search for go.mod.
-       } else if LoaderState.RootMode == NoRoot {
+       } else if loaderstate.RootMode == NoRoot {
                if cfg.ModFile != "" && !base.InGOFLAGS("-modfile") {
                        base.Fatalf("go: -modfile cannot be used with commands that ignore the current module")
                }
-               LoaderState.modRoots = nil
-       } else if LoaderState.workFilePath != "" {
+               loaderstate.modRoots = nil
+       } else if loaderstate.workFilePath != "" {
                // We're in workspace mode, which implies module mode.
                if cfg.ModFile != "" {
                        base.Fatalf("go: -modfile cannot be used in workspace mode")
@@ -514,7 +514,7 @@ func Init() {
                        if cfg.ModFile != "" {
                                base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.")
                        }
-                       if LoaderState.RootMode == NeedRoot {
+                       if loaderstate.RootMode == NeedRoot {
                                base.Fatal(ErrNoModRoot)
                        }
                        if !mustUseModules {
@@ -529,14 +529,14 @@ func Init() {
                        // It's a bit of a peculiar thing to disallow but quite mysterious
                        // when it happens. See golang.org/issue/26708.
                        fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir())
-                       if LoaderState.RootMode == NeedRoot {
+                       if loaderstate.RootMode == NeedRoot {
                                base.Fatal(ErrNoModRoot)
                        }
                        if !mustUseModules {
                                return
                        }
                } else {
-                       LoaderState.modRoots = []string{modRoot}
+                       loaderstate.modRoots = []string{modRoot}
                }
        }
        if cfg.ModFile != "" && !strings.HasSuffix(cfg.ModFile, ".mod") {
@@ -545,13 +545,13 @@ func Init() {
 
        // We're in module mode. Set any global variables that need to be set.
        cfg.ModulesEnabled = true
-       setDefaultBuildMod()
+       setDefaultBuildMod(loaderstate)
        list := filepath.SplitList(cfg.BuildContext.GOPATH)
        if len(list) > 0 && list[0] != "" {
                gopath = list[0]
                if _, err := fsys.Stat(filepath.Join(gopath, "go.mod")); err == nil {
                        fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in $GOPATH %v\n", gopath)
-                       if LoaderState.RootMode == NeedRoot {
+                       if loaderstate.RootMode == NeedRoot {
                                base.Fatal(ErrNoModRoot)
                        }
                        if !mustUseModules {
@@ -622,49 +622,49 @@ func FindGoMod(wd string) string {
 // If modules are enabled but there is no main module, Enabled returns true
 // and then the first use of module information will call die
 // (usually through MustModRoot).
-func Enabled() bool {
-       Init()
-       return LoaderState.modRoots != nil || cfg.ModulesEnabled
+func Enabled(loaderstate *State) bool {
+       Init(loaderstate)
+       return loaderstate.modRoots != nil || cfg.ModulesEnabled
 }
 
-func VendorDir() string {
-       if inWorkspaceMode() {
-               return filepath.Join(filepath.Dir(WorkFilePath()), "vendor")
+func VendorDir(loaderstate *State) string {
+       if inWorkspaceMode(loaderstate) {
+               return filepath.Join(filepath.Dir(WorkFilePath(loaderstate)), "vendor")
        }
        // Even if -mod=vendor, we could be operating with no mod root (and thus no
        // vendor directory). As long as there are no dependencies that is expected
        // to work. See script/vendor_outside_module.txt.
-       modRoot := LoaderState.MainModules.ModRoot(LoaderState.MainModules.mustGetSingleMainModule())
+       modRoot := loaderstate.MainModules.ModRoot(loaderstate.MainModules.mustGetSingleMainModule(loaderstate))
        if modRoot == "" {
                panic("vendor directory does not exist when in single module mode outside of a module")
        }
        return filepath.Join(modRoot, "vendor")
 }
 
-func inWorkspaceMode() bool {
-       if !LoaderState.initialized {
+func inWorkspaceMode(loaderstate *State) bool {
+       if !loaderstate.initialized {
                panic("inWorkspaceMode called before modload.Init called")
        }
-       if !Enabled() {
+       if !Enabled(loaderstate) {
                return false
        }
-       return LoaderState.workFilePath != ""
+       return loaderstate.workFilePath != ""
 }
 
 // HasModRoot reports whether a main module or main modules are present.
 // HasModRoot may return false even if Enabled returns true: for example, 'get'
 // does not require a main module.
-func HasModRoot() bool {
-       Init()
-       return LoaderState.modRoots != nil
+func HasModRoot(loaderstate *State) bool {
+       Init(loaderstate)
+       return loaderstate.modRoots != nil
 }
 
 // MustHaveModRoot checks that a main module or main modules are present,
 // and calls base.Fatalf if there are no main modules.
 func MustHaveModRoot() {
-       Init()
-       if !HasModRoot() {
-               die()
+       Init(LoaderState)
+       if !HasModRoot(LoaderState) {
+               die(LoaderState)
        }
 }
 
@@ -686,11 +686,11 @@ func modFilePath(modRoot string) string {
        return filepath.Join(modRoot, "go.mod")
 }
 
-func die() {
+func die(loaderstate *State) {
        if cfg.Getenv("GO111MODULE") == "off" {
                base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
        }
-       if !inWorkspaceMode() {
+       if !inWorkspaceMode(loaderstate) {
                if dir, name := findAltConfig(base.Cwd()); dir != "" {
                        rel, err := filepath.Rel(base.Cwd(), dir)
                        if err != nil {
@@ -711,7 +711,7 @@ func die() {
 type noMainModulesError struct{}
 
 func (e noMainModulesError) Error() string {
-       if inWorkspaceMode() {
+       if inWorkspaceMode(LoaderState) {
                return "no modules were found in the current workspace; see 'go help work'"
        }
        return "go.mod file not found in current directory or any parent directory; see 'go help modules'"
@@ -868,33 +868,33 @@ func UpdateWorkFile(wf *modfile.WorkFile) {
 // other, but unlike LoadModGraph does not load the full module graph or check
 // it for global consistency. Most callers outside of the modload package should
 // use LoadModGraph instead.
-func LoadModFile(ctx context.Context) *Requirements {
-       rs, err := loadModFile(ctx, nil)
+func LoadModFile(loaderstate *State, ctx context.Context) *Requirements {
+       rs, err := loadModFile(loaderstate, ctx, nil)
        if err != nil {
                base.Fatal(err)
        }
        return rs
 }
 
-func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) {
-       if LoaderState.requirements != nil {
-               return LoaderState.requirements, nil
+func loadModFile(loaderstate *State, ctx context.Context, opts *PackageOpts) (*Requirements, error) {
+       if loaderstate.requirements != nil {
+               return loaderstate.requirements, nil
        }
 
-       Init()
+       Init(loaderstate)
        var workFile *modfile.WorkFile
-       if inWorkspaceMode() {
+       if inWorkspaceMode(loaderstate) {
                var err error
-               workFile, LoaderState.modRoots, err = LoadWorkFile(LoaderState.workFilePath)
+               workFile, loaderstate.modRoots, err = LoadWorkFile(loaderstate.workFilePath)
                if err != nil {
                        return nil, err
                }
-               for _, modRoot := range LoaderState.modRoots {
+               for _, modRoot := range loaderstate.modRoots {
                        sumFile := strings.TrimSuffix(modFilePath(modRoot), ".mod") + ".sum"
                        modfetch.WorkspaceGoSumFiles = append(modfetch.WorkspaceGoSumFiles, sumFile)
                }
-               modfetch.GoSumFile = LoaderState.workFilePath + ".sum"
-       } else if len(LoaderState.modRoots) == 0 {
+               modfetch.GoSumFile = loaderstate.workFilePath + ".sum"
+       } else if len(loaderstate.modRoots) == 0 {
                // We're in module mode, but not inside a module.
                //
                // Commands like 'go build', 'go run', 'go list' have no go.mod file to
@@ -913,25 +913,25 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                //
                // See golang.org/issue/32027.
        } else {
-               modfetch.GoSumFile = strings.TrimSuffix(modFilePath(LoaderState.modRoots[0]), ".mod") + ".sum"
+               modfetch.GoSumFile = strings.TrimSuffix(modFilePath(loaderstate.modRoots[0]), ".mod") + ".sum"
        }
-       if len(LoaderState.modRoots) == 0 {
+       if len(loaderstate.modRoots) == 0 {
                // TODO(#49228): Instead of creating a fake module with an empty modroot,
                // make MainModules.Len() == 0 mean that we're in module mode but not inside
                // any module.
                mainModule := module.Version{Path: "command-line-arguments"}
-               LoaderState.MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, nil)
+               loaderstate.MainModules = makeMainModules(loaderstate, []module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, nil)
                var (
                        goVersion string
                        pruning   modPruning
                        roots     []module.Version
                        direct    = map[string]bool{"go": true}
                )
-               if inWorkspaceMode() {
+               if inWorkspaceMode(loaderstate) {
                        // Since we are in a workspace, the Go version for the synthetic
                        // "command-line-arguments" module must not exceed the Go version
                        // for the workspace.
-                       goVersion = LoaderState.MainModules.GoVersion()
+                       goVersion = loaderstate.MainModules.GoVersion(loaderstate)
                        pruning = workspace
                        roots = []module.Version{
                                mainModule,
@@ -947,26 +947,26 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                        }
                }
                rawGoVersion.Store(mainModule, goVersion)
-               LoaderState.requirements = newRequirements(pruning, roots, direct)
+               loaderstate.requirements = newRequirements(loaderstate, pruning, roots, direct)
                if cfg.BuildMod == "vendor" {
                        // For issue 56536: Some users may have GOFLAGS=-mod=vendor set.
                        // Make sure it behaves as though the fake module is vendored
                        // with no dependencies.
-                       LoaderState.requirements.initVendor(nil)
+                       loaderstate.requirements.initVendor(loaderstate, nil)
                }
-               return LoaderState.requirements, nil
+               return loaderstate.requirements, nil
        }
 
        var modFiles []*modfile.File
        var mainModules []module.Version
        var indices []*modFileIndex
        var errs []error
-       for _, modroot := range LoaderState.modRoots {
+       for _, modroot := range loaderstate.modRoots {
                gomod := modFilePath(modroot)
                var fixed bool
-               data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed))
+               data, f, err := ReadModFile(gomod, fixVersion(loaderstate, ctx, &fixed))
                if err != nil {
-                       if inWorkspaceMode() {
+                       if inWorkspaceMode(loaderstate) {
                                if tooNew, ok := err.(*gover.TooNewError); ok && !strings.HasPrefix(cfg.CmdName, "work ") {
                                        // Switching to a newer toolchain won't help - the go.work has the wrong version.
                                        // Report this more specific error, unless we are a command like 'go work use'
@@ -981,7 +981,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                        errs = append(errs, err)
                        continue
                }
-               if inWorkspaceMode() && !strings.HasPrefix(cfg.CmdName, "work ") {
+               if inWorkspaceMode(loaderstate) && !strings.HasPrefix(cfg.CmdName, "work ") {
                        // Refuse to use workspace if its go version is too old.
                        // Disable this check if we are a workspace command like work use or work sync,
                        // which will fix the problem.
@@ -993,7 +993,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                        }
                }
 
-               if !inWorkspaceMode() {
+               if !inWorkspaceMode(loaderstate) {
                        ok := true
                        for _, g := range f.Godebug {
                                if err := CheckGodebug("godebug", g.Key, g.Value); err != nil {
@@ -1022,45 +1022,45 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                return nil, errors.Join(errs...)
        }
 
-       LoaderState.MainModules = makeMainModules(mainModules, LoaderState.modRoots, modFiles, indices, workFile)
-       setDefaultBuildMod() // possibly enable automatic vendoring
-       rs := requirementsFromModFiles(ctx, workFile, modFiles, opts)
+       loaderstate.MainModules = makeMainModules(loaderstate, mainModules, loaderstate.modRoots, modFiles, indices, workFile)
+       setDefaultBuildMod(loaderstate) // possibly enable automatic vendoring
+       rs := requirementsFromModFiles(loaderstate, ctx, workFile, modFiles, opts)
 
        if cfg.BuildMod == "vendor" {
-               readVendorList(VendorDir())
-               versions := LoaderState.MainModules.Versions()
+               readVendorList(VendorDir(loaderstate))
+               versions := loaderstate.MainModules.Versions()
                indexes := make([]*modFileIndex, 0, len(versions))
                modFiles := make([]*modfile.File, 0, len(versions))
                modRoots := make([]string, 0, len(versions))
                for _, m := range versions {
-                       indexes = append(indexes, LoaderState.MainModules.Index(m))
-                       modFiles = append(modFiles, LoaderState.MainModules.ModFile(m))
-                       modRoots = append(modRoots, LoaderState.MainModules.ModRoot(m))
+                       indexes = append(indexes, loaderstate.MainModules.Index(m))
+                       modFiles = append(modFiles, loaderstate.MainModules.ModFile(m))
+                       modRoots = append(modRoots, loaderstate.MainModules.ModRoot(m))
                }
-               checkVendorConsistency(indexes, modFiles, modRoots)
-               rs.initVendor(vendorList)
+               checkVendorConsistency(loaderstate, indexes, modFiles, modRoots)
+               rs.initVendor(loaderstate, vendorList)
        }
 
-       if inWorkspaceMode() {
+       if inWorkspaceMode(loaderstate) {
                // We don't need to update the mod file so return early.
-               LoaderState.requirements = rs
+               loaderstate.requirements = rs
                return rs, nil
        }
 
-       mainModule := LoaderState.MainModules.mustGetSingleMainModule()
+       mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate)
 
-       if rs.hasRedundantRoot() {
+       if rs.hasRedundantRoot(loaderstate) {
                // If any module path appears more than once in the roots, we know that the
                // go.mod file needs to be updated even though we have not yet loaded any
                // transitive dependencies.
                var err error
-               rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
+               rs, err = updateRoots(loaderstate, ctx, rs.direct, rs, nil, nil, false)
                if err != nil {
                        return nil, err
                }
        }
 
-       if LoaderState.MainModules.Index(mainModule).goVersion == "" && rs.pruning != workspace {
+       if loaderstate.MainModules.Index(mainModule).goVersion == "" && rs.pruning != workspace {
                // TODO(#45551): Do something more principled instead of checking
                // cfg.CmdName directly here.
                if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" {
@@ -1069,8 +1069,8 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                        if opts != nil && opts.TidyGoVersion != "" {
                                v = opts.TidyGoVersion
                        }
-                       addGoStmt(LoaderState.MainModules.ModFile(mainModule), mainModule, v)
-                       rs = overrideRoots(ctx, rs, []module.Version{{Path: "go", Version: v}})
+                       addGoStmt(loaderstate.MainModules.ModFile(mainModule), mainModule, v)
+                       rs = overrideRoots(loaderstate, ctx, rs, []module.Version{{Path: "go", Version: v}})
 
                        // We need to add a 'go' version to the go.mod file, but we must assume
                        // that its existing contents match something between Go 1.11 and 1.16.
@@ -1079,7 +1079,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                        // requirements to support pruning.
                        if gover.Compare(v, gover.ExplicitIndirectVersion) >= 0 {
                                var err error
-                               rs, err = convertPruning(ctx, rs, pruned)
+                               rs, err = convertPruning(loaderstate, ctx, rs, pruned)
                                if err != nil {
                                        return nil, err
                                }
@@ -1089,8 +1089,8 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
                }
        }
 
-       LoaderState.requirements = rs
-       return LoaderState.requirements, nil
+       loaderstate.requirements = rs
+       return loaderstate.requirements, nil
 }
 
 func errWorkTooOld(gomod string, wf *modfile.WorkFile, goVers string) error {
@@ -1126,7 +1126,7 @@ func CheckReservedModulePath(path string) error {
 func CreateModFile(ctx context.Context, modPath string) {
        modRoot := base.Cwd()
        LoaderState.modRoots = []string{modRoot}
-       Init()
+       Init(LoaderState)
        modFilePath := modFilePath(modRoot)
        if _, err := fsys.Stat(modFilePath); err == nil {
                base.Fatalf("go: %s already exists", modFilePath)
@@ -1162,16 +1162,16 @@ func CreateModFile(ctx context.Context, modPath string) {
        fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath)
        modFile := new(modfile.File)
        modFile.AddModuleStmt(modPath)
-       LoaderState.MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, nil)
+       LoaderState.MainModules = makeMainModules(LoaderState, []module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil}, nil)
        addGoStmt(modFile, modFile.Module.Mod, gover.Local()) // Add the go directive before converted module requirements.
 
-       rs := requirementsFromModFiles(ctx, nil, []*modfile.File{modFile}, nil)
-       rs, err := updateRoots(ctx, rs.direct, rs, nil, nil, false)
+       rs := requirementsFromModFiles(LoaderState, ctx, nil, []*modfile.File{modFile}, nil)
+       rs, err := updateRoots(LoaderState, ctx, rs.direct, rs, nil, nil, false)
        if err != nil {
                base.Fatal(err)
        }
        LoaderState.requirements = rs
-       if err := commitRequirements(ctx, WriteOpts{}); err != nil {
+       if err := commitRequirements(LoaderState, ctx, WriteOpts{}); err != nil {
                base.Fatal(err)
        }
 
@@ -1206,7 +1206,7 @@ func CreateModFile(ctx context.Context, modPath string) {
 // and does nothing for versions that already appear to be canonical.
 //
 // The VersionFixer sets 'fixed' if it ever returns a non-canonical version.
-func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer {
+func fixVersion(loaderstate *State, ctx context.Context, fixed *bool) modfile.VersionFixer {
        return func(path, vers string) (resolved string, err error) {
                defer func() {
                        if err == nil && resolved != vers {
@@ -1239,7 +1239,7 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer {
                        return vers, nil
                }
 
-               info, err := Query(ctx, path, vers, "", nil)
+               info, err := Query(loaderstate, ctx, path, vers, "", nil)
                if err != nil {
                        return "", err
                }
@@ -1254,8 +1254,8 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer {
 //
 // This function affects the default cfg.BuildMod when outside of a module,
 // so it can only be called prior to Init.
-func AllowMissingModuleImports() {
-       if LoaderState.initialized {
+func AllowMissingModuleImports(loaderstate *State) {
+       if loaderstate.initialized {
                panic("AllowMissingModuleImports after Init")
        }
        allowMissingModuleImports = true
@@ -1263,7 +1263,7 @@ func AllowMissingModuleImports() {
 
 // makeMainModules creates a MainModuleSet and associated variables according to
 // the given main modules.
-func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFile *modfile.WorkFile) *MainModuleSet {
+func makeMainModules(loaderstate *State, ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex, workFile *modfile.WorkFile) *MainModuleSet {
        for _, m := range ms {
                if m.Version != "" {
                        panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m))
@@ -1338,7 +1338,7 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile
                                        continue
                                }
                                var newV module.Version = r.New
-                               if WorkFilePath() != "" && newV.Version == "" && !filepath.IsAbs(newV.Path) {
+                               if WorkFilePath(loaderstate) != "" && newV.Version == "" && !filepath.IsAbs(newV.Path) {
                                        // Since we are in a workspace, we may be loading replacements from
                                        // multiple go.mod files. Relative paths in those replacement are
                                        // relative to the go.mod file, not the workspace, so the same string
@@ -1380,14 +1380,14 @@ func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile
 
 // requirementsFromModFiles returns the set of non-excluded requirements from
 // the global modFile.
-func requirementsFromModFiles(ctx context.Context, workFile *modfile.WorkFile, modFiles []*modfile.File, opts *PackageOpts) *Requirements {
+func requirementsFromModFiles(loaderstate *State, ctx context.Context, workFile *modfile.WorkFile, modFiles []*modfile.File, opts *PackageOpts) *Requirements {
        var roots []module.Version
        direct := map[string]bool{}
        var pruning modPruning
-       if inWorkspaceMode() {
+       if inWorkspaceMode(loaderstate) {
                pruning = workspace
-               roots = make([]module.Version, len(LoaderState.MainModules.Versions()), 2+len(LoaderState.MainModules.Versions()))
-               copy(roots, LoaderState.MainModules.Versions())
+               roots = make([]module.Version, len(loaderstate.MainModules.Versions()), 2+len(loaderstate.MainModules.Versions()))
+               copy(roots, loaderstate.MainModules.Versions())
                goVersion := gover.FromGoWork(workFile)
                var toolchain string
                if workFile.Toolchain != nil {
@@ -1396,16 +1396,16 @@ func requirementsFromModFiles(ctx context.Context, workFile *modfile.WorkFile, m
                roots = appendGoAndToolchainRoots(roots, goVersion, toolchain, direct)
                direct = directRequirements(modFiles)
        } else {
-               pruning = pruningForGoVersion(LoaderState.MainModules.GoVersion())
+               pruning = pruningForGoVersion(loaderstate.MainModules.GoVersion(loaderstate))
                if len(modFiles) != 1 {
                        panic(fmt.Errorf("requirementsFromModFiles called with %v modfiles outside workspace mode", len(modFiles)))
                }
                modFile := modFiles[0]
-               roots, direct = rootsFromModFile(LoaderState.MainModules.mustGetSingleMainModule(), modFile, withToolchainRoot)
+               roots, direct = rootsFromModFile(loaderstate, loaderstate.MainModules.mustGetSingleMainModule(loaderstate), modFile, withToolchainRoot)
        }
 
        gover.ModSort(roots)
-       rs := newRequirements(pruning, roots, direct)
+       rs := newRequirements(loaderstate, pruning, roots, direct)
        return rs
 }
 
@@ -1428,7 +1428,7 @@ func directRequirements(modFiles []*modfile.File) map[string]bool {
        return direct
 }
 
-func rootsFromModFile(m module.Version, modFile *modfile.File, addToolchainRoot addToolchainRoot) (roots []module.Version, direct map[string]bool) {
+func rootsFromModFile(loaderstate *State, m module.Version, modFile *modfile.File, addToolchainRoot addToolchainRoot) (roots []module.Version, direct map[string]bool) {
        direct = make(map[string]bool)
        padding := 2 // Add padding for the toolchain and go version, added upon return.
        if !addToolchainRoot {
@@ -1436,7 +1436,7 @@ func rootsFromModFile(m module.Version, modFile *modfile.File, addToolchainRoot
        }
        roots = make([]module.Version, 0, padding+len(modFile.Require))
        for _, r := range modFile.Require {
-               if index := LoaderState.MainModules.Index(m); index != nil && index.exclude[r.Mod] {
+               if index := loaderstate.MainModules.Index(m); index != nil && index.exclude[r.Mod] {
                        if cfg.BuildMod == "mod" {
                                fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version)
                        } else {
@@ -1477,9 +1477,9 @@ func appendGoAndToolchainRoots(roots []module.Version, goVersion, toolchain stri
 
 // setDefaultBuildMod sets a default value for cfg.BuildMod if the -mod flag
 // wasn't provided. setDefaultBuildMod may be called multiple times.
-func setDefaultBuildMod() {
+func setDefaultBuildMod(loaderstate *State) {
        if cfg.BuildModExplicit {
-               if inWorkspaceMode() && cfg.BuildMod != "readonly" && cfg.BuildMod != "vendor" {
+               if inWorkspaceMode(loaderstate) && cfg.BuildMod != "readonly" && cfg.BuildMod != "vendor" {
                        switch cfg.CmdName {
                        case "work sync", "mod graph", "mod verify", "mod why":
                                // These commands run with BuildMod set to mod, but they don't take the
@@ -1514,7 +1514,7 @@ func setDefaultBuildMod() {
                cfg.BuildMod = "readonly"
                return
        }
-       if LoaderState.modRoots == nil {
+       if loaderstate.modRoots == nil {
                if allowMissingModuleImports {
                        cfg.BuildMod = "mod"
                } else {
@@ -1523,29 +1523,29 @@ func setDefaultBuildMod() {
                return
        }
 
-       if len(LoaderState.modRoots) >= 1 {
+       if len(loaderstate.modRoots) >= 1 {
                var goVersion string
                var versionSource string
-               if inWorkspaceMode() {
+               if inWorkspaceMode(loaderstate) {
                        versionSource = "go.work"
-                       if wfg := LoaderState.MainModules.WorkFile().Go; wfg != nil {
+                       if wfg := loaderstate.MainModules.WorkFile().Go; wfg != nil {
                                goVersion = wfg.Version
                        }
                } else {
                        versionSource = "go.mod"
-                       index := LoaderState.MainModules.GetSingleIndexOrNil()
+                       index := loaderstate.MainModules.GetSingleIndexOrNil(loaderstate)
                        if index != nil {
                                goVersion = index.goVersion
                        }
                }
                vendorDir := ""
-               if LoaderState.workFilePath != "" {
-                       vendorDir = filepath.Join(filepath.Dir(LoaderState.workFilePath), "vendor")
+               if loaderstate.workFilePath != "" {
+                       vendorDir = filepath.Join(filepath.Dir(loaderstate.workFilePath), "vendor")
                } else {
-                       if len(LoaderState.modRoots) != 1 {
-                               panic(fmt.Errorf("outside workspace mode, but have %v modRoots", LoaderState.modRoots))
+                       if len(loaderstate.modRoots) != 1 {
+                               panic(fmt.Errorf("outside workspace mode, but have %v modRoots", loaderstate.modRoots))
                        }
-                       vendorDir = filepath.Join(LoaderState.modRoots[0], "vendor")
+                       vendorDir = filepath.Join(loaderstate.modRoots[0], "vendor")
                }
                if fi, err := fsys.Stat(vendorDir); err == nil && fi.IsDir() {
                        if goVersion != "" {
@@ -1613,8 +1613,8 @@ func modulesTextIsForWorkspace(vendorDir string) (bool, error) {
        return false, nil
 }
 
-func mustHaveCompleteRequirements() bool {
-       return cfg.BuildMod != "mod" && !inWorkspaceMode()
+func mustHaveCompleteRequirements(loaderstate *State) bool {
+       return cfg.BuildMod != "mod" && !inWorkspaceMode(loaderstate)
 }
 
 // addGoStmt adds a go directive to the go.mod file if it does not already
@@ -1809,21 +1809,21 @@ type WriteOpts struct {
 
 // WriteGoMod writes the current build list back to go.mod.
 func WriteGoMod(ctx context.Context, opts WriteOpts) error {
-       LoaderState.requirements = LoadModFile(ctx)
-       return commitRequirements(ctx, opts)
+       LoaderState.requirements = LoadModFile(LoaderState, ctx)
+       return commitRequirements(LoaderState, ctx, opts)
 }
 
 var errNoChange = errors.New("no update needed")
 
 // UpdateGoModFromReqs returns a modified go.mod file using the current
 // requirements. It does not commit these changes to disk.
-func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []byte, modFile *modfile.File, err error) {
-       if LoaderState.MainModules.Len() != 1 || LoaderState.MainModules.ModRoot(LoaderState.MainModules.Versions()[0]) == "" {
+func UpdateGoModFromReqs(loaderstate *State, ctx context.Context, opts WriteOpts) (before, after []byte, modFile *modfile.File, err error) {
+       if loaderstate.MainModules.Len() != 1 || loaderstate.MainModules.ModRoot(loaderstate.MainModules.Versions()[0]) == "" {
                // We aren't in a module, so we don't have anywhere to write a go.mod file.
                return nil, nil, nil, errNoChange
        }
-       mainModule := LoaderState.MainModules.mustGetSingleMainModule()
-       modFile = LoaderState.MainModules.ModFile(mainModule)
+       mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate)
+       modFile = loaderstate.MainModules.ModFile(mainModule)
        if modFile == nil {
                // command-line-arguments has no .mod file to write.
                return nil, nil, nil, errNoChange
@@ -1836,7 +1836,7 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b
        var list []*modfile.Require
        toolchain := ""
        goVersion := ""
-       for _, m := range LoaderState.requirements.rootModules {
+       for _, m := range loaderstate.requirements.rootModules {
                if m.Path == "go" {
                        goVersion = m.Version
                        continue
@@ -1847,7 +1847,7 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b
                }
                list = append(list, &modfile.Require{
                        Mod:      m,
-                       Indirect: !LoaderState.requirements.direct[m.Path],
+                       Indirect: !loaderstate.requirements.direct[m.Path],
                })
        }
 
@@ -1917,13 +1917,13 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b
 // go.mod or go.sum are out of date in a semantically significant way.
 //
 // In workspace mode, commitRequirements only writes changes to go.work.sum.
-func commitRequirements(ctx context.Context, opts WriteOpts) (err error) {
-       if inWorkspaceMode() {
+func commitRequirements(loaderstate *State, ctx context.Context, opts WriteOpts) (err error) {
+       if inWorkspaceMode(loaderstate) {
                // go.mod files aren't updated in workspace mode, but we still want to
                // update the go.work.sum file.
-               return modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements())
+               return modfetch.WriteGoSum(ctx, keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums), mustHaveCompleteRequirements(loaderstate))
        }
-       _, updatedGoMod, modFile, err := UpdateGoModFromReqs(ctx, opts)
+       _, updatedGoMod, modFile, err := UpdateGoModFromReqs(loaderstate, ctx, opts)
        if err != nil {
                if errors.Is(err, errNoChange) {
                        return nil
@@ -1931,7 +1931,7 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) {
                return err
        }
 
-       index := LoaderState.MainModules.GetSingleIndexOrNil()
+       index := loaderstate.MainModules.GetSingleIndexOrNil(loaderstate)
        dirty := index.modFileIsDirty(modFile) || len(opts.DropTools) > 0 || len(opts.AddTools) > 0
        if dirty && cfg.BuildMod != "mod" {
                // If we're about to fail due to -mod=readonly,
@@ -1945,15 +1945,15 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) {
                // Don't write go.mod, but write go.sum in case we added or trimmed sums.
                // 'go mod init' shouldn't write go.sum, since it will be incomplete.
                if cfg.CmdName != "mod init" {
-                       if err := modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil {
+                       if err := modfetch.WriteGoSum(ctx, keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums), mustHaveCompleteRequirements(loaderstate)); err != nil {
                                return err
                        }
                }
                return nil
        }
 
-       mainModule := LoaderState.MainModules.mustGetSingleMainModule()
-       modFilePath := modFilePath(LoaderState.MainModules.ModRoot(mainModule))
+       mainModule := loaderstate.MainModules.mustGetSingleMainModule(loaderstate)
+       modFilePath := modFilePath(loaderstate.MainModules.ModRoot(mainModule))
        if fsys.Replaced(modFilePath) {
                if dirty {
                        return errors.New("updates to go.mod needed, but go.mod is part of the overlay specified with -overlay")
@@ -1962,13 +1962,13 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) {
        }
        defer func() {
                // At this point we have determined to make the go.mod file on disk equal to new.
-               LoaderState.MainModules.SetIndex(mainModule, indexModFile(updatedGoMod, modFile, mainModule, false))
+               loaderstate.MainModules.SetIndex(mainModule, indexModFile(updatedGoMod, modFile, mainModule, false))
 
                // Update go.sum after releasing the side lock and refreshing the index.
                // 'go mod init' shouldn't write go.sum, since it will be incomplete.
                if cfg.CmdName != "mod init" {
                        if err == nil {
-                               err = modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements())
+                               err = modfetch.WriteGoSum(ctx, keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums), mustHaveCompleteRequirements(loaderstate))
                        }
                }
        }()
@@ -2011,7 +2011,7 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) {
 // including any go.mod files needed to reconstruct the MVS result
 // or identify go versions,
 // in addition to the checksums for every module in keepMods.
-func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums) map[module.Version]bool {
+func keepSums(loaderstate *State, ctx context.Context, ld *loader, rs *Requirements, which whichSums) map[module.Version]bool {
        // Every module in the full module graph contributes its requirements,
        // so in order to ensure that the build list itself is reproducible,
        // we need sums for every go.mod in the graph (regardless of whether
@@ -2024,12 +2024,12 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums
        // ambiguous import errors the next time we load the package.
        keepModSumsForZipSums := true
        if ld == nil {
-               if gover.Compare(LoaderState.MainModules.GoVersion(), gover.TidyGoModSumVersion) < 0 && cfg.BuildMod != "mod" {
+               if gover.Compare(loaderstate.MainModules.GoVersion(loaderstate), gover.TidyGoModSumVersion) < 0 && cfg.BuildMod != "mod" {
                        keepModSumsForZipSums = false
                }
        } else {
                keepPkgGoModSums := true
-               if gover.Compare(ld.requirements.GoVersion(), gover.TidyGoModSumVersion) < 0 && (ld.Tidy || cfg.BuildMod != "mod") {
+               if gover.Compare(ld.requirements.GoVersion(loaderstate), gover.TidyGoModSumVersion) < 0 && (ld.Tidy || cfg.BuildMod != "mod") {
                        keepPkgGoModSums = false
                        keepModSumsForZipSums = false
                }
@@ -2047,21 +2047,21 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums
                        // minor, so we maintain the previous (buggy) behavior in 'go mod tidy' to
                        // avoid introducing unnecessary churn.
                        if keepPkgGoModSums {
-                               r := resolveReplacement(pkg.mod)
+                               r := resolveReplacement(loaderstate, pkg.mod)
                                keep[modkey(r)] = true
                        }
 
                        if rs.pruning == pruned && pkg.mod.Path != "" {
-                               if v, ok := rs.rootSelected(pkg.mod.Path); ok && v == pkg.mod.Version {
+                               if v, ok := rs.rootSelected(loaderstate, pkg.mod.Path); ok && v == pkg.mod.Version {
                                        // pkg was loaded from a root module, and because the main module has
                                        // a pruned module graph we do not check non-root modules for
                                        // conflicts for packages that can be found in roots. So we only need
                                        // the checksums for the root modules that may contain pkg, not all
                                        // possible modules.
                                        for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) {
-                                               if v, ok := rs.rootSelected(prefix); ok && v != "none" {
+                                               if v, ok := rs.rootSelected(loaderstate, prefix); ok && v != "none" {
                                                        m := module.Version{Path: prefix, Version: v}
-                                                       r := resolveReplacement(m)
+                                                       r := resolveReplacement(loaderstate, m)
                                                        keep[r] = true
                                                }
                                        }
@@ -2069,11 +2069,11 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums
                                }
                        }
 
-                       mg, _ := rs.Graph(ctx)
+                       mg, _ := rs.Graph(loaderstate, ctx)
                        for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) {
                                if v := mg.Selected(prefix); v != "none" {
                                        m := module.Version{Path: prefix, Version: v}
-                                       r := resolveReplacement(m)
+                                       r := resolveReplacement(loaderstate, m)
                                        keep[r] = true
                                }
                        }
@@ -2085,27 +2085,27 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums
                // Save sums for the root modules (or their replacements), but don't
                // incur the cost of loading the graph just to find and retain the sums.
                for _, m := range rs.rootModules {
-                       r := resolveReplacement(m)
+                       r := resolveReplacement(loaderstate, m)
                        keep[modkey(r)] = true
                        if which == addBuildListZipSums {
                                keep[r] = true
                        }
                }
        } else {
-               mg, _ := rs.Graph(ctx)
+               mg, _ := rs.Graph(loaderstate, ctx)
                mg.WalkBreadthFirst(func(m module.Version) {
                        if _, ok := mg.RequiredBy(m); ok {
                                // The requirements from m's go.mod file are present in the module graph,
                                // so they are relevant to the MVS result regardless of whether m was
                                // actually selected.
-                               r := resolveReplacement(m)
+                               r := resolveReplacement(loaderstate, m)
                                keep[modkey(r)] = true
                        }
                })
 
                if which == addBuildListZipSums {
                        for _, m := range mg.BuildList() {
-                               r := resolveReplacement(m)
+                               r := resolveReplacement(loaderstate, m)
                                if keepModSumsForZipSums {
                                        keep[modkey(r)] = true // we need the go version from the go.mod file to do anything useful with the zipfile
                                }
index 803bab49ae96bbccf950d4c334eadbd6107e8580..bd28d7596e160a6ce5809b3e0816aa89afea7768 100644 (file)
@@ -69,7 +69,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st
                }
        }
 
-       rs, mods, err := listModules(ctx, LoadModFile(ctx), args, mode, reuse)
+       rs, mods, err := listModules(ctx, LoadModFile(LoaderState, ctx), args, mode, reuse)
 
        type token struct{}
        sem := make(chan token, runtime.GOMAXPROCS(0))
@@ -88,7 +88,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st
                                                addVersions(ctx, m, mode&ListRetractedVersions != 0)
                                        }
                                        if mode&ListRetracted != 0 {
-                                               addRetraction(ctx, m)
+                                               addRetraction(LoaderState, ctx, m)
                                        }
                                        if mode&ListDeprecated != 0 {
                                                addDeprecation(ctx, m)
@@ -117,7 +117,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st
                // but in general list -u is looking up other checksums in the checksum database
                // that won't be necessary later, so it makes sense not to write the go.sum back out.
                if !ExplicitWriteGoMod && mode&ListU == 0 {
-                       err = commitRequirements(ctx, WriteOpts{})
+                       err = commitRequirements(LoaderState, ctx, WriteOpts{})
                }
        }
        return mods, err
@@ -130,7 +130,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                        if gover.IsToolchain(m.Path) {
                                continue
                        }
-                       ms = append(ms, moduleInfo(ctx, rs, m, mode, reuse))
+                       ms = append(ms, moduleInfo(LoaderState, ctx, rs, m, mode, reuse))
                }
                return rs, ms, nil
        }
@@ -145,25 +145,25 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                }
                if arg == "all" || strings.Contains(arg, "...") {
                        needFullGraph = true
-                       if !HasModRoot() {
+                       if !HasModRoot(LoaderState) {
                                base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
                        }
                        continue
                }
                if path, vers, found := strings.Cut(arg, "@"); found {
                        if vers == "upgrade" || vers == "patch" {
-                               if _, ok := rs.rootSelected(path); !ok || rs.pruning == unpruned {
+                               if _, ok := rs.rootSelected(LoaderState, path); !ok || rs.pruning == unpruned {
                                        needFullGraph = true
-                                       if !HasModRoot() {
+                                       if !HasModRoot(LoaderState) {
                                                base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
                                        }
                                }
                        }
                        continue
                }
-               if _, ok := rs.rootSelected(arg); !ok || rs.pruning == unpruned {
+               if _, ok := rs.rootSelected(LoaderState, arg); !ok || rs.pruning == unpruned {
                        needFullGraph = true
-                       if mode&ListVersions == 0 && !HasModRoot() {
+                       if mode&ListVersions == 0 && !HasModRoot(LoaderState) {
                                base.Fatalf("go: cannot match %q without -versions or an explicit version: %v", arg, ErrNoModRoot)
                        }
                }
@@ -171,7 +171,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
 
        var mg *ModuleGraph
        if needFullGraph {
-               rs, mg, mgErr = expandGraph(ctx, rs)
+               rs, mg, mgErr = expandGraph(LoaderState, ctx, rs)
        }
 
        matchedModule := map[module.Version]bool{}
@@ -179,7 +179,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                if path, vers, found := strings.Cut(arg, "@"); found {
                        var current string
                        if mg == nil {
-                               current, _ = rs.rootSelected(path)
+                               current, _ = rs.rootSelected(LoaderState, path)
                        } else {
                                current = mg.Selected(path)
                        }
@@ -198,7 +198,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                                // specific revision or used 'go list -retracted'.
                                allowed = nil
                        }
-                       info, err := queryReuse(ctx, path, vers, current, allowed, reuse)
+                       info, err := queryReuse(LoaderState, ctx, path, vers, current, allowed, reuse)
                        if err != nil {
                                var origin *codehost.Origin
                                if info != nil {
@@ -217,7 +217,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                        // *Requirements instead.
                        var noRS *Requirements
 
-                       mod := moduleInfo(ctx, noRS, module.Version{Path: path, Version: info.Version}, mode, reuse)
+                       mod := moduleInfo(LoaderState, ctx, noRS, module.Version{Path: path, Version: info.Version}, mode, reuse)
                        if vers != mod.Version {
                                mod.Query = vers
                        }
@@ -237,7 +237,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                        var v string
                        if mg == nil {
                                var ok bool
-                               v, ok = rs.rootSelected(arg)
+                               v, ok = rs.rootSelected(LoaderState, arg)
                                if !ok {
                                        // We checked rootSelected(arg) in the earlier args loop, so if there
                                        // is no such root we should have loaded a non-nil mg.
@@ -251,7 +251,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                                continue
                        }
                        if v != "none" {
-                               mods = append(mods, moduleInfo(ctx, rs, module.Version{Path: arg, Version: v}, mode, reuse))
+                               mods = append(mods, moduleInfo(LoaderState, ctx, rs, module.Version{Path: arg, Version: v}, mode, reuse))
                        } else if cfg.BuildMod == "vendor" {
                                // In vendor mode, we can't determine whether a missing module is “a
                                // known dependency” because the module graph is incomplete.
@@ -292,7 +292,7 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
                fetchedMods := make([]*modinfo.ModulePublic, len(matches))
                for i, m := range matches {
                        q.Add(func() {
-                               fetchedMods[i] = moduleInfo(ctx, rs, m, mode, reuse)
+                               fetchedMods[i] = moduleInfo(LoaderState, ctx, rs, m, mode, reuse)
                        })
                }
                <-q.Idle()
index 0d661eb2e7b0be016438a774b1a178dbff55220d..ad3b80bfd954aa0e62b7ffe9aa0a46680a56362a 100644 (file)
@@ -250,7 +250,7 @@ type PackageOpts struct {
 
 // LoadPackages identifies the set of packages matching the given patterns and
 // loads the packages in the import graph rooted at that set.
-func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) {
+func LoadPackages(loaderstate *State, ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) {
        if opts.Tags == nil {
                opts.Tags = imports.Tags()
        }
@@ -271,11 +271,11 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                        case m.IsLocal():
                                // Evaluate list of file system directories on first iteration.
                                if m.Dirs == nil {
-                                       matchModRoots := LoaderState.modRoots
+                                       matchModRoots := loaderstate.modRoots
                                        if opts.MainModule != (module.Version{}) {
-                                               matchModRoots = []string{LoaderState.MainModules.ModRoot(opts.MainModule)}
+                                               matchModRoots = []string{loaderstate.MainModules.ModRoot(opts.MainModule)}
                                        }
-                                       matchLocalDirs(ctx, matchModRoots, m, rs)
+                                       matchLocalDirs(loaderstate, ctx, matchModRoots, m, rs)
                                }
 
                                // Make a copy of the directory list and translate to import paths.
@@ -286,7 +286,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                                // the loader iterations.
                                m.Pkgs = m.Pkgs[:0]
                                for _, dir := range m.Dirs {
-                                       pkg, err := resolveLocalPackage(ctx, dir, rs)
+                                       pkg, err := resolveLocalPackage(loaderstate, ctx, dir, rs)
                                        if err != nil {
                                                if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) {
                                                        continue // Don't include "builtin" or GOROOT/src in wildcard patterns.
@@ -294,8 +294,8 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
 
                                                // If we're outside of a module, ensure that the failure mode
                                                // indicates that.
-                                               if !HasModRoot() {
-                                                       die()
+                                               if !HasModRoot(loaderstate) {
+                                                       die(loaderstate)
                                                }
 
                                                if ld != nil {
@@ -311,7 +311,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
 
                        case strings.Contains(m.Pattern(), "..."):
                                m.Errs = m.Errs[:0]
-                               mg, err := rs.Graph(ctx)
+                               mg, err := rs.Graph(loaderstate, ctx)
                                if err != nil {
                                        // The module graph is (or may be) incomplete — perhaps we failed to
                                        // load the requirements of some module. This is an error in matching
@@ -321,26 +321,26 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                                        // necessarily prevent us from loading the packages we could find.
                                        m.Errs = append(m.Errs, err)
                                }
-                               matchPackages(ctx, m, opts.Tags, includeStd, mg.BuildList())
+                               matchPackages(loaderstate, ctx, m, opts.Tags, includeStd, mg.BuildList())
 
                        case m.Pattern() == "work":
-                               matchModules := LoaderState.MainModules.Versions()
+                               matchModules := loaderstate.MainModules.Versions()
                                if opts.MainModule != (module.Version{}) {
                                        matchModules = []module.Version{opts.MainModule}
                                }
-                               matchPackages(ctx, m, opts.Tags, omitStd, matchModules)
+                               matchPackages(loaderstate, ctx, m, opts.Tags, omitStd, matchModules)
 
                        case m.Pattern() == "all":
                                if ld == nil {
                                        // The initial roots are the packages and tools in the main module.
                                        // loadFromRoots will expand that to "all".
                                        m.Errs = m.Errs[:0]
-                                       matchModules := LoaderState.MainModules.Versions()
+                                       matchModules := loaderstate.MainModules.Versions()
                                        if opts.MainModule != (module.Version{}) {
                                                matchModules = []module.Version{opts.MainModule}
                                        }
-                                       matchPackages(ctx, m, opts.Tags, omitStd, matchModules)
-                                       for tool := range LoaderState.MainModules.Tools() {
+                                       matchPackages(loaderstate, ctx, m, opts.Tags, omitStd, matchModules)
+                                       for tool := range loaderstate.MainModules.Tools() {
                                                m.Pkgs = append(m.Pkgs, tool)
                                        }
                                } else {
@@ -355,7 +355,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                                }
 
                        case m.Pattern() == "tool":
-                               for tool := range LoaderState.MainModules.Tools() {
+                               for tool := range loaderstate.MainModules.Tools() {
                                        m.Pkgs = append(m.Pkgs, tool)
                                }
                        default:
@@ -364,12 +364,12 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                }
        }
 
-       initialRS, err := loadModFile(ctx, &opts)
+       initialRS, err := loadModFile(loaderstate, ctx, &opts)
        if err != nil {
                base.Fatal(err)
        }
 
-       ld := loadFromRoots(ctx, loaderParams{
+       ld := loadFromRoots(loaderstate, ctx, loaderParams{
                PackageOpts:  opts,
                requirements: initialRS,
 
@@ -404,7 +404,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
 
        if opts.Tidy {
                if cfg.BuildV {
-                       mg, _ := ld.requirements.Graph(ctx)
+                       mg, _ := ld.requirements.Graph(loaderstate, ctx)
                        for _, m := range initialRS.rootModules {
                                var unused bool
                                if ld.requirements.pruning == unpruned {
@@ -416,7 +416,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                                        // m is unused if it was dropped from the roots. If it is still present
                                        // as a transitive dependency, that transitive dependency is not needed
                                        // by any package or test in the main module.
-                                       _, ok := ld.requirements.rootSelected(m.Path)
+                                       _, ok := ld.requirements.rootSelected(loaderstate, m.Path)
                                        unused = !ok
                                }
                                if unused {
@@ -425,9 +425,9 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                        }
                }
 
-               keep := keepSums(ctx, ld, ld.requirements, loadedZipSumsOnly)
+               keep := keepSums(loaderstate, ctx, ld, ld.requirements, loadedZipSumsOnly)
                compatVersion := ld.TidyCompatibleVersion
-               goVersion := ld.requirements.GoVersion()
+               goVersion := ld.requirements.GoVersion(loaderstate)
                if compatVersion == "" {
                        if gover.Compare(goVersion, gover.GoStrictVersion) < 0 {
                                compatVersion = gover.Prev(goVersion)
@@ -444,10 +444,10 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                        compatVersion = goVersion
                }
                if compatPruning := pruningForGoVersion(compatVersion); compatPruning != ld.requirements.pruning {
-                       compatRS := newRequirements(compatPruning, ld.requirements.rootModules, ld.requirements.direct)
-                       ld.checkTidyCompatibility(ctx, compatRS, compatVersion)
+                       compatRS := newRequirements(loaderstate, compatPruning, ld.requirements.rootModules, ld.requirements.direct)
+                       ld.checkTidyCompatibility(loaderstate, ctx, compatRS, compatVersion)
 
-                       for m := range keepSums(ctx, ld, compatRS, loadedZipSumsOnly) {
+                       for m := range keepSums(loaderstate, ctx, ld, compatRS, loadedZipSumsOnly) {
                                keep[m] = true
                        }
                }
@@ -455,8 +455,8 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                if opts.TidyDiff {
                        cfg.BuildMod = "readonly"
                        loaded = ld
-                       LoaderState.requirements = loaded.requirements
-                       currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(ctx, WriteOpts{})
+                       loaderstate.requirements = loaded.requirements
+                       currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(loaderstate, ctx, WriteOpts{})
                        if err != nil {
                                base.Fatal(err)
                        }
@@ -466,7 +466,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                        // Dropping compatibility for 1.16 may result in a strictly smaller go.sum.
                        // Update the keep map with only the loaded.requirements.
                        if gover.Compare(compatVersion, "1.16") > 0 {
-                               keep = keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums)
+                               keep = keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums)
                        }
                        currentGoSum, tidyGoSum := modfetch.TidyGoSum(keep)
                        goSumDiff := diff.Diff("current/go.sum", currentGoSum, "tidy/go.sum", tidyGoSum)
@@ -490,7 +490,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
                        // loaded.requirements, but here we may have also loaded (and want to
                        // preserve checksums for) additional entities from compatRS, which are
                        // only needed for compatibility with ld.TidyCompatibleVersion.
-                       if err := modfetch.WriteGoSum(ctx, keep, mustHaveCompleteRequirements()); err != nil {
+                       if err := modfetch.WriteGoSum(ctx, keep, mustHaveCompleteRequirements(loaderstate)); err != nil {
                                base.Fatal(err)
                        }
                }
@@ -505,7 +505,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
        // to call WriteGoMod itself) or if ResolveMissingImports is false (the
        // command wants to examine the package graph as-is).
        loaded = ld
-       LoaderState.requirements = loaded.requirements
+       loaderstate.requirements = loaded.requirements
 
        for _, pkg := range ld.pkgs {
                if !pkg.isTest() {
@@ -515,7 +515,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
        sort.Strings(loadedPackages)
 
        if !ExplicitWriteGoMod && opts.ResolveMissingImports {
-               if err := commitRequirements(ctx, WriteOpts{}); err != nil {
+               if err := commitRequirements(loaderstate, ctx, WriteOpts{}); err != nil {
                        base.Fatal(err)
                }
        }
@@ -525,7 +525,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
 
 // matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories
 // outside of the standard library and active modules.
-func matchLocalDirs(ctx context.Context, modRoots []string, m *search.Match, rs *Requirements) {
+func matchLocalDirs(loaderstate *State, ctx context.Context, modRoots []string, m *search.Match, rs *Requirements) {
        if !m.IsLocal() {
                panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern()))
        }
@@ -543,10 +543,10 @@ func matchLocalDirs(ctx context.Context, modRoots []string, m *search.Match, rs
                }
 
                modRoot := findModuleRoot(absDir)
-               if !slices.Contains(modRoots, modRoot) && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(ctx, absDir, rs) == "" {
+               if !slices.Contains(modRoots, modRoot) && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(loaderstate, ctx, absDir, rs) == "" {
                        m.Dirs = []string{}
                        scope := "main module or its selected dependencies"
-                       if inWorkspaceMode() {
+                       if inWorkspaceMode(loaderstate) {
                                scope = "modules listed in go.work or their selected dependencies"
                        }
                        m.AddError(fmt.Errorf("directory prefix %s does not contain %s", base.ShortPath(absDir), scope))
@@ -558,7 +558,7 @@ func matchLocalDirs(ctx context.Context, modRoots []string, m *search.Match, rs
 }
 
 // resolveLocalPackage resolves a filesystem path to a package path.
-func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (string, error) {
+func resolveLocalPackage(loaderstate *State, ctx context.Context, dir string, rs *Requirements) (string, error) {
        var absDir string
        if filepath.IsAbs(dir) {
                absDir = filepath.Clean(dir)
@@ -596,13 +596,13 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str
                }
        }
 
-       for _, mod := range LoaderState.MainModules.Versions() {
-               modRoot := LoaderState.MainModules.ModRoot(mod)
+       for _, mod := range loaderstate.MainModules.Versions() {
+               modRoot := loaderstate.MainModules.ModRoot(mod)
                if modRoot != "" && absDir == modRoot {
                        if absDir == cfg.GOROOTsrc {
                                return "", errPkgIsGorootSrc
                        }
-                       return LoaderState.MainModules.PathPrefix(mod), nil
+                       return loaderstate.MainModules.PathPrefix(mod), nil
                }
        }
 
@@ -611,8 +611,8 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str
        // It's not strictly necessary but helpful to keep the checks.
        var pkgNotFoundErr error
        pkgNotFoundLongestPrefix := ""
-       for _, mainModule := range LoaderState.MainModules.Versions() {
-               modRoot := LoaderState.MainModules.ModRoot(mainModule)
+       for _, mainModule := range loaderstate.MainModules.Versions() {
+               modRoot := loaderstate.MainModules.ModRoot(mainModule)
                if modRoot != "" && str.HasFilePathPrefix(absDir, modRoot) && !strings.Contains(absDir[len(modRoot):], "@") {
                        suffix := filepath.ToSlash(str.TrimFilePathPrefix(absDir, modRoot))
                        if pkg, found := strings.CutPrefix(suffix, "vendor/"); found {
@@ -620,14 +620,14 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str
                                        return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir)
                                }
 
-                               readVendorList(VendorDir())
+                               readVendorList(VendorDir(loaderstate))
                                if _, ok := vendorPkgModule[pkg]; !ok {
                                        return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir)
                                }
                                return pkg, nil
                        }
 
-                       mainModulePrefix := LoaderState.MainModules.PathPrefix(mainModule)
+                       mainModulePrefix := loaderstate.MainModules.PathPrefix(mainModule)
                        if mainModulePrefix == "" {
                                pkg := suffix
                                if pkg == "builtin" {
@@ -668,13 +668,13 @@ func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (str
                return pkg, nil
        }
 
-       pkg := pathInModuleCache(ctx, absDir, rs)
+       pkg := pathInModuleCache(loaderstate, ctx, absDir, rs)
        if pkg == "" {
                dirstr := fmt.Sprintf("directory %s", base.ShortPath(absDir))
                if dirstr == "directory ." {
                        dirstr = "current directory"
                }
-               if inWorkspaceMode() {
+               if inWorkspaceMode(loaderstate) {
                        if mr := findModuleRoot(absDir); mr != "" {
                                return "", fmt.Errorf("%s is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use %s", dirstr, base.ShortPath(mr))
                        }
@@ -693,17 +693,17 @@ var (
 
 // pathInModuleCache returns the import path of the directory dir,
 // if dir is in the module cache copy of a module in our build list.
-func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string {
+func pathInModuleCache(loaderstate *State, ctx context.Context, dir string, rs *Requirements) string {
        tryMod := func(m module.Version) (string, bool) {
                if gover.IsToolchain(m.Path) {
                        return "", false
                }
                var root string
                var err error
-               if repl := Replacement(m); repl.Path != "" && repl.Version == "" {
+               if repl := Replacement(loaderstate, m); repl.Path != "" && repl.Version == "" {
                        root = repl.Path
                        if !filepath.IsAbs(root) {
-                               root = filepath.Join(replaceRelativeTo(), root)
+                               root = filepath.Join(replaceRelativeTo(loaderstate), root)
                        }
                } else if repl.Path != "" {
                        root, err = modfetch.DownloadDir(ctx, repl)
@@ -728,7 +728,7 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string
 
        if rs.pruning == pruned {
                for _, m := range rs.rootModules {
-                       if v, _ := rs.rootSelected(m.Path); v != m.Version {
+                       if v, _ := rs.rootSelected(loaderstate, m.Path); v != m.Version {
                                continue // m is a root, but we have a higher root for the same path.
                        }
                        if importPath, ok := tryMod(m); ok {
@@ -747,7 +747,7 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string
        // versions of root modules may differ from what we already checked above.
        // Re-check those paths too.
 
-       mg, _ := rs.Graph(ctx)
+       mg, _ := rs.Graph(loaderstate, ctx)
        var importPath string
        for _, m := range mg.BuildList() {
                var found bool
@@ -766,8 +766,8 @@ func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string
 //
 // TODO(bcmills): Silencing errors seems off. Take a closer look at this and
 // figure out what the error-reporting actually ought to be.
-func ImportFromFiles(ctx context.Context, gofiles []string) {
-       rs := LoadModFile(ctx)
+func ImportFromFiles(loaderstate *State, ctx context.Context, gofiles []string) {
+       rs := LoadModFile(loaderstate, ctx)
 
        tags := imports.Tags()
        imports, testImports, err := imports.ScanFiles(gofiles, tags)
@@ -775,7 +775,7 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
                base.Fatal(err)
        }
 
-       loaded = loadFromRoots(ctx, loaderParams{
+       loaded = loadFromRoots(loaderstate, ctx, loaderParams{
                PackageOpts: PackageOpts{
                        Tags:                  tags,
                        ResolveMissingImports: true,
@@ -788,10 +788,10 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
                        return roots
                },
        })
-       LoaderState.requirements = loaded.requirements
+       loaderstate.requirements = loaded.requirements
 
        if !ExplicitWriteGoMod {
-               if err := commitRequirements(ctx, WriteOpts{}); err != nil {
+               if err := commitRequirements(loaderstate, ctx, WriteOpts{}); err != nil {
                        base.Fatal(err)
                }
        }
@@ -799,11 +799,11 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
 
 // DirImportPath returns the effective import path for dir,
 // provided it is within a main module, or else returns ".".
-func (mms *MainModuleSet) DirImportPath(ctx context.Context, dir string) (path string, m module.Version) {
-       if !HasModRoot() {
+func (mms *MainModuleSet) DirImportPath(loaderstate *State, ctx context.Context, dir string) (path string, m module.Version) {
+       if !HasModRoot(loaderstate) {
                return ".", module.Version{}
        }
-       LoadModFile(ctx) // Sets targetPrefix.
+       LoadModFile(loaderstate, ctx) // Sets targetPrefix.
 
        if !filepath.IsAbs(dir) {
                dir = filepath.Join(base.Cwd(), dir)
@@ -820,7 +820,7 @@ func (mms *MainModuleSet) DirImportPath(ctx context.Context, dir string) (path s
                        return mms.PathPrefix(v), v
                }
                if str.HasFilePathPrefix(dir, modRoot) {
-                       pathPrefix := LoaderState.MainModules.PathPrefix(v)
+                       pathPrefix := loaderstate.MainModules.PathPrefix(v)
                        if pathPrefix > longestPrefix {
                                longestPrefix = pathPrefix
                                longestPrefixVersion = v
@@ -853,13 +853,13 @@ func PackageModule(path string) module.Version {
 // the package at path as imported from the package in parentDir.
 // Lookup requires that one of the Load functions in this package has already
 // been called.
-func Lookup(parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) {
+func Lookup(loaderstate *State, parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) {
        if path == "" {
                panic("Lookup called with empty package path")
        }
 
        if parentIsStd {
-               path = loaded.stdVendor(parentPath, path)
+               path = loaded.stdVendor(loaderstate, parentPath, path)
        }
        pkg, ok := loaded.pkgCache.Get(path)
        if !ok {
@@ -957,11 +957,11 @@ func (ld *loader) exitIfErrors(ctx context.Context) {
 // goVersion reports the Go version that should be used for the loader's
 // requirements: ld.TidyGoVersion if set, or ld.requirements.GoVersion()
 // otherwise.
-func (ld *loader) goVersion() string {
+func (ld *loader) goVersion(loaderstate *State) string {
        if ld.TidyGoVersion != "" {
                return ld.TidyGoVersion
        }
-       return ld.requirements.GoVersion()
+       return ld.requirements.GoVersion(loaderstate)
 }
 
 // A loadPkg records information about a single loaded package.
@@ -1064,11 +1064,11 @@ func (pkg *loadPkg) isTest() bool {
 
 // fromExternalModule reports whether pkg was loaded from a module other than
 // the main module.
-func (pkg *loadPkg) fromExternalModule() bool {
+func (pkg *loadPkg) fromExternalModule(loaderstate *State) bool {
        if pkg.mod.Path == "" {
                return false // loaded from the standard library, not a module
        }
-       return !LoaderState.MainModules.Contains(pkg.mod.Path)
+       return !loaderstate.MainModules.Contains(pkg.mod.Path)
 }
 
 var errMissing = errors.New("cannot find package")
@@ -1079,7 +1079,7 @@ var errMissing = errors.New("cannot find package")
 // The set of root packages is returned by the params.listRoots function, and
 // expanded to the full set of packages by tracing imports (and possibly tests)
 // as needed.
-func loadFromRoots(ctx context.Context, params loaderParams) *loader {
+func loadFromRoots(loaderstate *State, ctx context.Context, params loaderParams) *loader {
        ld := &loader{
                loaderParams: params,
                work:         par.NewQueue(runtime.GOMAXPROCS(0)),
@@ -1095,7 +1095,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                // spot-checks in modules that do not maintain the expanded go.mod
                // requirements needed for graph pruning.
                var err error
-               ld.requirements, _, err = expandGraph(ctx, ld.requirements)
+               ld.requirements, _, err = expandGraph(loaderstate, ctx, ld.requirements)
                if err != nil {
                        ld.error(err)
                }
@@ -1103,11 +1103,11 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
        ld.exitIfErrors(ctx)
 
        updateGoVersion := func() {
-               goVersion := ld.goVersion()
+               goVersion := ld.goVersion(loaderstate)
 
                if ld.requirements.pruning != workspace {
                        var err error
-                       ld.requirements, err = convertPruning(ctx, ld.requirements, pruningForGoVersion(goVersion))
+                       ld.requirements, err = convertPruning(loaderstate, ctx, ld.requirements, pruningForGoVersion(goVersion))
                        if err != nil {
                                ld.error(err)
                                ld.exitIfErrors(ctx)
@@ -1141,7 +1141,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                        // set of root packages does not change then we can select the correct
                        // versions of all transitive imports on the first try and complete
                        // loading in a single iteration.
-                       changedBuildList := ld.preloadRootModules(ctx, rootPkgs)
+                       changedBuildList := ld.preloadRootModules(loaderstate, ctx, rootPkgs)
                        if changedBuildList {
                                // The build list has changed, so the set of root packages may have also
                                // changed. Start over to pick up the changes. (Preloading roots is much
@@ -1154,7 +1154,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
 
                inRoots := map[*loadPkg]bool{}
                for _, path := range rootPkgs {
-                       root := ld.pkg(ctx, path, pkgIsRoot)
+                       root := ld.pkg(loaderstate, ctx, path, pkgIsRoot)
                        if !inRoots[root] {
                                ld.roots = append(ld.roots, root)
                                inRoots[root] = true
@@ -1170,7 +1170,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
 
                ld.buildStacks()
 
-               changed, err := ld.updateRequirements(ctx)
+               changed, err := ld.updateRequirements(loaderstate, ctx)
                if err != nil {
                        ld.error(err)
                        break
@@ -1184,12 +1184,12 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                        continue
                }
 
-               if !ld.ResolveMissingImports || (!HasModRoot() && !allowMissingModuleImports) {
+               if !ld.ResolveMissingImports || (!HasModRoot(loaderstate) && !allowMissingModuleImports) {
                        // We've loaded as much as we can without resolving missing imports.
                        break
                }
 
-               modAddedBy, err := ld.resolveMissingImports(ctx)
+               modAddedBy, err := ld.resolveMissingImports(loaderstate, ctx)
                if err != nil {
                        ld.error(err)
                        break
@@ -1216,7 +1216,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                // iteration so we don't need to also update it here. (That would waste time
                // computing a "direct" map that we'll have to recompute later anyway.)
                direct := ld.requirements.direct
-               rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported)
+               rs, err := updateRoots(loaderstate, ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported)
                if err != nil {
                        // If an error was found in a newly added module, report the package
                        // import stack instead of the module requirement stack. Packages
@@ -1244,7 +1244,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
        // Tidy the build list, if applicable, before we report errors.
        // (The process of tidying may remove errors from irrelevant dependencies.)
        if ld.Tidy {
-               rs, err := tidyRoots(ctx, ld.requirements, ld.pkgs)
+               rs, err := tidyRoots(loaderstate, ctx, ld.requirements, ld.pkgs)
                if err != nil {
                        ld.error(err)
                } else {
@@ -1252,8 +1252,8 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                                // Attempt to switch to the requested Go version. We have been using its
                                // pruning and semantics all along, but there may have been — and may
                                // still be — requirements on higher versions in the graph.
-                               tidy := overrideRoots(ctx, rs, []module.Version{{Path: "go", Version: ld.TidyGoVersion}})
-                               mg, err := tidy.Graph(ctx)
+                               tidy := overrideRoots(loaderstate, ctx, rs, []module.Version{{Path: "go", Version: ld.TidyGoVersion}})
+                               mg, err := tidy.Graph(loaderstate, ctx)
                                if err != nil {
                                        ld.error(err)
                                }
@@ -1285,7 +1285,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                                        if m.Path == "go" && ld.TidyGoVersion != "" {
                                                continue
                                        }
-                                       if v, ok := ld.requirements.rootSelected(m.Path); !ok || v != m.Version {
+                                       if v, ok := ld.requirements.rootSelected(loaderstate, m.Path); !ok || v != m.Version {
                                                ld.error(fmt.Errorf("internal error: a requirement on %v is needed but was not added during package loading (selected %s)", m, v))
                                        }
                                }
@@ -1334,7 +1334,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                ld.error(fmt.Errorf("%s: %w", pkg.stackText(), pkg.err))
        }
 
-       ld.checkMultiplePaths()
+       ld.checkMultiplePaths(loaderstate)
        return ld
 }
 
@@ -1357,7 +1357,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
 // The "changed" return value reports whether the update changed the selected
 // version of any module that either provided a loaded package or may now
 // provide a package that was previously unresolved.
-func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err error) {
+func (ld *loader) updateRequirements(loaderstate *State, ctx context.Context) (changed bool, err error) {
        rs := ld.requirements
 
        // direct contains the set of modules believed to provide packages directly
@@ -1390,16 +1390,16 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
                                }
                        }
                }
-               if pkg.mod.Version != "" || !LoaderState.MainModules.Contains(pkg.mod.Path) {
+               if pkg.mod.Version != "" || !loaderstate.MainModules.Contains(pkg.mod.Path) {
                        continue
                }
 
                for _, dep := range pkg.imports {
-                       if !dep.fromExternalModule() {
+                       if !dep.fromExternalModule(loaderstate) {
                                continue
                        }
 
-                       if inWorkspaceMode() {
+                       if inWorkspaceMode(loaderstate) {
                                // In workspace mode / workspace pruning mode, the roots are the main modules
                                // rather than the main module's direct dependencies. The check below on the selected
                                // roots does not apply.
@@ -1412,7 +1412,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
                                        // of the vendor directory anyway.
                                        continue
                                }
-                               if mg, err := rs.Graph(ctx); err != nil {
+                               if mg, err := rs.Graph(loaderstate, ctx); err != nil {
                                        return false, err
                                } else if _, ok := mg.RequiredBy(dep.mod); !ok {
                                        // dep.mod is not an explicit dependency, but needs to be.
@@ -1424,7 +1424,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
                                        }
                                }
                        } else if pkg.err == nil && cfg.BuildMod != "mod" {
-                               if v, ok := rs.rootSelected(dep.mod.Path); !ok || v != dep.mod.Version {
+                               if v, ok := rs.rootSelected(loaderstate, dep.mod.Path); !ok || v != dep.mod.Version {
                                        // dep.mod is not an explicit dependency, but needs to be.
                                        // Because we are not in "mod" mode, we will not be able to update it.
                                        // Instead, mark the importing package with an error.
@@ -1490,21 +1490,21 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
                // roots can only increase and the set of roots can only expand. The set
                // of extant root paths is finite and the set of versions of each path is
                // finite, so the iteration *must* reach a stable fixed-point.
-               tidy, err := tidyRoots(ctx, rs, ld.pkgs)
+               tidy, err := tidyRoots(loaderstate, ctx, rs, ld.pkgs)
                if err != nil {
                        return false, err
                }
                addRoots = tidy.rootModules
        }
 
-       rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported)
+       rs, err = updateRoots(loaderstate, ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported)
        if err != nil {
                // We don't actually know what even the root requirements are supposed to be,
                // so we can't proceed with loading. Return the error to the caller
                return false, err
        }
 
-       if rs.GoVersion() != ld.requirements.GoVersion() {
+       if rs.GoVersion(loaderstate) != ld.requirements.GoVersion(loaderstate) {
                // A change in the selected Go version may or may not affect the set of
                // loaded packages, but in some cases it can change the meaning of the "all"
                // pattern, the level of pruning in the module graph, and even the set of
@@ -1515,12 +1515,12 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
                // The roots of the module graph have changed in some way (not just the
                // "direct" markings). Check whether the changes affected any of the loaded
                // packages.
-               mg, err := rs.Graph(ctx)
+               mg, err := rs.Graph(loaderstate, ctx)
                if err != nil {
                        return false, err
                }
                for _, pkg := range ld.pkgs {
-                       if pkg.fromExternalModule() && mg.Selected(pkg.mod.Path) != pkg.mod.Version {
+                       if pkg.fromExternalModule(loaderstate) && mg.Selected(pkg.mod.Path) != pkg.mod.Version {
                                changed = true
                                break
                        }
@@ -1540,7 +1540,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
                                //
                                // In some sense, we can think of this as ‘upgraded the module providing
                                // pkg.path from "none" to a version higher than "none"’.
-                               if _, _, _, _, err = importFromModules(ctx, pkg.path, rs, nil, ld.skipImportModFiles); err == nil {
+                               if _, _, _, _, err = importFromModules(loaderstate, ctx, pkg.path, rs, nil, ld.skipImportModFiles); err == nil {
                                        changed = true
                                        break
                                }
@@ -1558,7 +1558,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
 // The newly-resolved packages are added to the addedModuleFor map, and
 // resolveMissingImports returns a map from each new module version to
 // the first missing package that module would resolve.
-func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[module.Version]*loadPkg, err error) {
+func (ld *loader) resolveMissingImports(loaderstate *State, ctx context.Context) (modAddedBy map[module.Version]*loadPkg, err error) {
        type pkgMod struct {
                pkg *loadPkg
                mod *module.Version
@@ -1582,11 +1582,11 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod
                var mod module.Version
                ld.work.Add(func() {
                        var err error
-                       mod, err = queryImport(ctx, pkg.path, ld.requirements)
+                       mod, err = queryImport(loaderstate, ctx, pkg.path, ld.requirements)
                        if err != nil {
                                if ime, ok := errors.AsType[*ImportMissingError](err); ok {
                                        for curstack := pkg.stack; curstack != nil; curstack = curstack.stack {
-                                               if LoaderState.MainModules.Contains(curstack.mod.Path) {
+                                               if loaderstate.MainModules.Contains(curstack.mod.Path) {
                                                        ime.ImportingMainModule = curstack.mod
                                                        break
                                                }
@@ -1658,7 +1658,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod
 // ld.work queue, and its test (if requested) will also be populated once
 // imports have been resolved. When ld.work goes idle, all transitive imports of
 // the requested package (and its test, if requested) will have been loaded.
-func (ld *loader) pkg(ctx context.Context, path string, flags loadPkgFlags) *loadPkg {
+func (ld *loader) pkg(loaderstate *State, ctx context.Context, path string, flags loadPkgFlags) *loadPkg {
        if flags.has(pkgImportsLoaded) {
                panic("internal error: (*loader).pkg called with pkgImportsLoaded flag set")
        }
@@ -1667,20 +1667,20 @@ func (ld *loader) pkg(ctx context.Context, path string, flags loadPkgFlags) *loa
                pkg := &loadPkg{
                        path: path,
                }
-               ld.applyPkgFlags(ctx, pkg, flags)
+               ld.applyPkgFlags(loaderstate, ctx, pkg, flags)
 
-               ld.work.Add(func() { ld.load(ctx, pkg) })
+               ld.work.Add(func() { ld.load(loaderstate, ctx, pkg) })
                return pkg
        })
 
-       ld.applyPkgFlags(ctx, pkg, flags)
+       ld.applyPkgFlags(loaderstate, ctx, pkg, flags)
        return pkg
 }
 
 // applyPkgFlags updates pkg.flags to set the given flags and propagate the
 // (transitive) effects of those flags, possibly loading or enqueueing further
 // packages as a result.
-func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkgFlags) {
+func (ld *loader) applyPkgFlags(loaderstate *State, ctx context.Context, pkg *loadPkg, flags loadPkgFlags) {
        if flags == 0 {
                return
        }
@@ -1708,7 +1708,7 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
                // so it's ok if we call it more than is strictly necessary.
                wantTest := false
                switch {
-               case ld.allPatternIsRoot && LoaderState.MainModules.Contains(pkg.mod.Path):
+               case ld.allPatternIsRoot && loaderstate.MainModules.Contains(pkg.mod.Path):
                        // We are loading the "all" pattern, which includes packages imported by
                        // tests in the main module. This package is in the main module, so we
                        // need to identify the imports of its test even if LoadTests is not set.
@@ -1729,13 +1729,13 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
 
                if wantTest {
                        var testFlags loadPkgFlags
-                       if LoaderState.MainModules.Contains(pkg.mod.Path) || (ld.allClosesOverTests && new.has(pkgInAll)) {
+                       if loaderstate.MainModules.Contains(pkg.mod.Path) || (ld.allClosesOverTests && new.has(pkgInAll)) {
                                // Tests of packages in the main module are in "all", in the sense that
                                // they cause the packages they import to also be in "all". So are tests
                                // of packages in "all" if "all" closes over test dependencies.
                                testFlags |= pkgInAll
                        }
-                       ld.pkgTest(ctx, pkg, testFlags)
+                       ld.pkgTest(loaderstate, ctx, pkg, testFlags)
                }
        }
 
@@ -1743,13 +1743,13 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
                // We have just marked pkg with pkgInAll, or we have just loaded its
                // imports, or both. Now is the time to propagate pkgInAll to the imports.
                for _, dep := range pkg.imports {
-                       ld.applyPkgFlags(ctx, dep, pkgInAll)
+                       ld.applyPkgFlags(loaderstate, ctx, dep, pkgInAll)
                }
        }
 
        if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {
                for _, dep := range pkg.imports {
-                       ld.applyPkgFlags(ctx, dep, pkgFromRoot)
+                       ld.applyPkgFlags(loaderstate, ctx, dep, pkgFromRoot)
                }
        }
 }
@@ -1757,7 +1757,7 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
 // preloadRootModules loads the module requirements needed to identify the
 // selected version of each module providing a package in rootPkgs,
 // adding new root modules to the module graph if needed.
-func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (changedBuildList bool) {
+func (ld *loader) preloadRootModules(loaderstate *State, ctx context.Context, rootPkgs []string) (changedBuildList bool) {
        needc := make(chan map[module.Version]bool, 1)
        needc <- map[module.Version]bool{}
        for _, path := range rootPkgs {
@@ -1768,12 +1768,12 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
                        // If the main module is tidy and the package is in "all" — or if we're
                        // lucky — we can identify all of its imports without actually loading the
                        // full module graph.
-                       m, _, _, _, err := importFromModules(ctx, path, ld.requirements, nil, ld.skipImportModFiles)
+                       m, _, _, _, err := importFromModules(loaderstate, ctx, path, ld.requirements, nil, ld.skipImportModFiles)
                        if err != nil {
                                if _, ok := errors.AsType[*ImportMissingError](err); ok && ld.ResolveMissingImports {
                                        // This package isn't provided by any selected module.
                                        // If we can find it, it will be a new root dependency.
-                                       m, err = queryImport(ctx, path, ld.requirements)
+                                       m, err = queryImport(loaderstate, ctx, path, ld.requirements)
                                }
                                if err != nil {
                                        // We couldn't identify the root module containing this package.
@@ -1786,7 +1786,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
                                return
                        }
 
-                       v, ok := ld.requirements.rootSelected(m.Path)
+                       v, ok := ld.requirements.rootSelected(loaderstate, m.Path)
                        if !ok || v != m.Version {
                                // We found the requested package in m, but m is not a root, so
                                // loadModGraph will not load its requirements. We need to promote the
@@ -1814,7 +1814,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
        }
        gover.ModSort(toAdd)
 
-       rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported)
+       rs, err := updateRoots(loaderstate, ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported)
        if err != nil {
                // We are missing some root dependency, and for some reason we can't load
                // enough of the module dependency graph to add the missing root. Package
@@ -1836,11 +1836,11 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
 }
 
 // load loads an individual package.
-func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
+func (ld *loader) load(loaderstate *State, ctx context.Context, pkg *loadPkg) {
        var mg *ModuleGraph
        if ld.requirements.pruning == unpruned {
                var err error
-               mg, err = ld.requirements.Graph(ctx)
+               mg, err = ld.requirements.Graph(loaderstate, ctx)
                if err != nil {
                        // We already checked the error from Graph in loadFromRoots and/or
                        // updateRequirements, so we ignored the error on purpose and we should
@@ -1855,17 +1855,17 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
        }
 
        var modroot string
-       pkg.mod, modroot, pkg.dir, pkg.altMods, pkg.err = importFromModules(ctx, pkg.path, ld.requirements, mg, ld.skipImportModFiles)
-       if LoaderState.MainModules.Tools()[pkg.path] {
+       pkg.mod, modroot, pkg.dir, pkg.altMods, pkg.err = importFromModules(loaderstate, ctx, pkg.path, ld.requirements, mg, ld.skipImportModFiles)
+       if loaderstate.MainModules.Tools()[pkg.path] {
                // Tools declared by main modules are always in "all".
                // We apply the package flags before returning so that missing
                // tool dependencies report an error https://go.dev/issue/70582
-               ld.applyPkgFlags(ctx, pkg, pkgInAll)
+               ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll)
        }
        if pkg.dir == "" {
                return
        }
-       if LoaderState.MainModules.Contains(pkg.mod.Path) {
+       if loaderstate.MainModules.Contains(pkg.mod.Path) {
                // Go ahead and mark pkg as in "all". This provides the invariant that a
                // package that is *only* imported by other packages in "all" is always
                // marked as such before loading its imports.
@@ -1875,7 +1875,7 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
                // about (by reducing churn on the flag bits of dependencies), and costs
                // essentially nothing (these atomic flag ops are essentially free compared
                // to scanning source code for imports).
-               ld.applyPkgFlags(ctx, pkg, pkgInAll)
+               ld.applyPkgFlags(loaderstate, ctx, pkg, pkgInAll)
        }
        if ld.AllowPackage != nil {
                if err := ld.AllowPackage(ctx, pkg.path, pkg.mod); err != nil {
@@ -1907,13 +1907,13 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
                if pkg.inStd {
                        // Imports from packages in "std" and "cmd" should resolve using
                        // GOROOT/src/vendor even when "std" is not the main module.
-                       path = ld.stdVendor(pkg.path, path)
+                       path = ld.stdVendor(loaderstate, pkg.path, path)
                }
-               pkg.imports = append(pkg.imports, ld.pkg(ctx, path, importFlags))
+               pkg.imports = append(pkg.imports, ld.pkg(loaderstate, ctx, path, importFlags))
        }
        pkg.testImports = testImports
 
-       ld.applyPkgFlags(ctx, pkg, pkgImportsLoaded)
+       ld.applyPkgFlags(loaderstate, ctx, pkg, pkgImportsLoaded)
 }
 
 // pkgTest locates the test of pkg, creating it if needed, and updates its state
@@ -1921,7 +1921,7 @@ func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
 //
 // pkgTest requires that the imports of pkg have already been loaded (flagged
 // with pkgImportsLoaded).
-func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
+func (ld *loader) pkgTest(loaderstate *State, ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {
        if pkg.isTest() {
                panic("pkgTest called on a test package")
        }
@@ -1936,7 +1936,7 @@ func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFl
                        err:    pkg.err,
                        inStd:  pkg.inStd,
                }
-               ld.applyPkgFlags(ctx, pkg.test, testFlags)
+               ld.applyPkgFlags(loaderstate, ctx, pkg.test, testFlags)
                createdTest = true
        })
 
@@ -1949,14 +1949,14 @@ func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFl
                }
                for _, path := range pkg.testImports {
                        if pkg.inStd {
-                               path = ld.stdVendor(test.path, path)
+                               path = ld.stdVendor(loaderstate, test.path, path)
                        }
-                       test.imports = append(test.imports, ld.pkg(ctx, path, importFlags))
+                       test.imports = append(test.imports, ld.pkg(loaderstate, ctx, path, importFlags))
                }
                pkg.testImports = nil
-               ld.applyPkgFlags(ctx, test, pkgImportsLoaded)
+               ld.applyPkgFlags(loaderstate, ctx, test, pkgImportsLoaded)
        } else {
-               ld.applyPkgFlags(ctx, test, testFlags)
+               ld.applyPkgFlags(loaderstate, ctx, test, testFlags)
        }
 
        return test
@@ -1964,7 +1964,7 @@ func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFl
 
 // stdVendor returns the canonical import path for the package with the given
 // path when imported from the standard-library package at parentPath.
-func (ld *loader) stdVendor(parentPath, path string) string {
+func (ld *loader) stdVendor(loaderstate *State, parentPath, path string) string {
        if p, _, ok := fips140.ResolveImport(path); ok {
                return p
        }
@@ -1973,14 +1973,14 @@ func (ld *loader) stdVendor(parentPath, path string) string {
        }
 
        if str.HasPathPrefix(parentPath, "cmd") {
-               if !ld.VendorModulesInGOROOTSrc || !LoaderState.MainModules.Contains("cmd") {
+               if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("cmd") {
                        vendorPath := pathpkg.Join("cmd", "vendor", path)
 
                        if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
                                return vendorPath
                        }
                }
-       } else if !ld.VendorModulesInGOROOTSrc || !LoaderState.MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") {
+       } else if !ld.VendorModulesInGOROOTSrc || !loaderstate.MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") {
                // If we are outside of the 'std' module, resolve imports from within 'std'
                // to the vendor directory.
                //
@@ -2026,7 +2026,7 @@ func (ld *loader) computePatternAll() (all []string) {
 // or as a replacement for another module, but not both at the same time.
 //
 // (See https://golang.org/issue/26607 and https://golang.org/issue/34650.)
-func (ld *loader) checkMultiplePaths() {
+func (ld *loader) checkMultiplePaths(loaderstate *State) {
        mods := ld.requirements.rootModules
        if cached := ld.requirements.graph.Load(); cached != nil {
                if mg := cached.mg; mg != nil {
@@ -2036,7 +2036,7 @@ func (ld *loader) checkMultiplePaths() {
 
        firstPath := map[module.Version]string{}
        for _, mod := range mods {
-               src := resolveReplacement(mod)
+               src := resolveReplacement(loaderstate, mod)
                if prev, ok := firstPath[src]; !ok {
                        firstPath[src] = mod.Path
                } else if prev != mod.Path {
@@ -2047,8 +2047,8 @@ func (ld *loader) checkMultiplePaths() {
 
 // checkTidyCompatibility emits an error if any package would be loaded from a
 // different module under rs than under ld.requirements.
-func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements, compatVersion string) {
-       goVersion := rs.GoVersion()
+func (ld *loader) checkTidyCompatibility(loaderstate *State, ctx context.Context, rs *Requirements, compatVersion string) {
+       goVersion := rs.GoVersion(loaderstate)
        suggestUpgrade := false
        suggestEFlag := false
        suggestFixes := func() {
@@ -2065,7 +2065,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements,
                fmt.Fprintln(os.Stderr)
 
                goFlag := ""
-               if goVersion != LoaderState.MainModules.GoVersion() {
+               if goVersion != loaderstate.MainModules.GoVersion(loaderstate) {
                        goFlag = " -go=" + goVersion
                }
 
@@ -2094,7 +2094,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements,
                fmt.Fprintf(os.Stderr, "For information about 'go mod tidy' compatibility, see:\n\thttps://go.dev/ref/mod#graph-pruning\n")
        }
 
-       mg, err := rs.Graph(ctx)
+       mg, err := rs.Graph(loaderstate, ctx)
        if err != nil {
                ld.error(fmt.Errorf("error loading go %s module graph: %w", compatVersion, err))
                ld.switchIfErrors(ctx)
@@ -2132,7 +2132,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements,
 
                pkg := pkg
                ld.work.Add(func() {
-                       mod, _, _, _, err := importFromModules(ctx, pkg.path, rs, mg, ld.skipImportModFiles)
+                       mod, _, _, _, err := importFromModules(loaderstate, ctx, pkg.path, rs, mg, ld.skipImportModFiles)
                        if mod != pkg.mod {
                                mismatches := <-mismatchMu
                                mismatches[pkg] = mismatch{mod: mod, err: err}
index 3fdbdc7010b993dad49b4a6bd62f847992324aa4..20feb8fcacc784b8a5cc37905944c2f611c9a95c 100644 (file)
@@ -142,7 +142,7 @@ func CheckAllowed(ctx context.Context, m module.Version) error {
        if err := CheckExclusions(ctx, m); err != nil {
                return err
        }
-       if err := CheckRetractions(ctx, m); err != nil {
+       if err := CheckRetractions(LoaderState, ctx, m); err != nil {
                return err
        }
        return nil
@@ -172,7 +172,7 @@ func (e *excludedError) Is(err error) bool { return err == ErrDisallowed }
 
 // CheckRetractions returns an error if module m has been retracted by
 // its author.
-func CheckRetractions(ctx context.Context, m module.Version) (err error) {
+func CheckRetractions(loaderstate *State, ctx context.Context, m module.Version) (err error) {
        defer func() {
                if err == nil {
                        return
@@ -193,7 +193,7 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) {
                // Cannot be retracted.
                return nil
        }
-       if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" {
+       if repl := Replacement(loaderstate, module.Version{Path: m.Path}); repl.Path != "" {
                // All versions of the module were replaced.
                // Don't load retractions, since we'd just load the replacement.
                return nil
@@ -210,11 +210,11 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) {
        // We load the raw file here: the go.mod file may have a different module
        // path that we expect if the module or its repository was renamed.
        // We still want to apply retractions to other aliases of the module.
-       rm, err := queryLatestVersionIgnoringRetractions(ctx, m.Path)
+       rm, err := queryLatestVersionIgnoringRetractions(loaderstate, ctx, m.Path)
        if err != nil {
                return err
        }
-       summary, err := rawGoModSummary(rm)
+       summary, err := rawGoModSummary(loaderstate, rm)
        if err != nil && !errors.Is(err, gover.ErrTooNew) {
                return err
        }
@@ -300,7 +300,7 @@ func ShortMessage(message, emptyDefault string) string {
 //
 // CheckDeprecation returns an error if the message can't be loaded.
 // CheckDeprecation returns "", nil if there is no deprecation message.
-func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string, err error) {
+func CheckDeprecation(loaderstate *State, ctx context.Context, m module.Version) (deprecation string, err error) {
        defer func() {
                if err != nil {
                        err = fmt.Errorf("loading deprecation for %s: %w", m.Path, err)
@@ -312,17 +312,17 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string
                // Don't look up deprecation.
                return "", nil
        }
-       if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" {
+       if repl := Replacement(loaderstate, module.Version{Path: m.Path}); repl.Path != "" {
                // All versions of the module were replaced.
                // We'll look up deprecation separately for the replacement.
                return "", nil
        }
 
-       latest, err := queryLatestVersionIgnoringRetractions(ctx, m.Path)
+       latest, err := queryLatestVersionIgnoringRetractions(loaderstate, ctx, m.Path)
        if err != nil {
                return "", err
        }
-       summary, err := rawGoModSummary(latest)
+       summary, err := rawGoModSummary(loaderstate, latest)
        if err != nil && !errors.Is(err, gover.ErrTooNew) {
                return "", err
        }
@@ -342,28 +342,28 @@ func replacement(mod module.Version, replace map[module.Version]module.Version)
 // Replacement returns the replacement for mod, if any. If the path in the
 // module.Version is relative it's relative to the single main module outside
 // workspace mode, or the workspace's directory in workspace mode.
-func Replacement(mod module.Version) module.Version {
-       r, foundModRoot, _ := replacementFrom(mod)
-       return canonicalizeReplacePath(r, foundModRoot)
+func Replacement(loaderstate *State, mod module.Version) module.Version {
+       r, foundModRoot, _ := replacementFrom(loaderstate, mod)
+       return canonicalizeReplacePath(loaderstate, r, foundModRoot)
 }
 
 // replacementFrom returns the replacement for mod, if any, the modroot of the replacement if it appeared in a go.mod,
 // and the source of the replacement. The replacement is relative to the go.work or go.mod file it appears in.
-func replacementFrom(mod module.Version) (r module.Version, modroot string, fromFile string) {
+func replacementFrom(loaderstate *State, mod module.Version) (r module.Version, modroot string, fromFile string) {
        foundFrom, found, foundModRoot := "", module.Version{}, ""
-       if LoaderState.MainModules == nil {
+       if loaderstate.MainModules == nil {
                return module.Version{}, "", ""
-       } else if LoaderState.MainModules.Contains(mod.Path) && mod.Version == "" {
+       } else if loaderstate.MainModules.Contains(mod.Path) && mod.Version == "" {
                // Don't replace the workspace version of the main module.
                return module.Version{}, "", ""
        }
-       if _, r, ok := replacement(mod, LoaderState.MainModules.WorkFileReplaceMap()); ok {
-               return r, "", LoaderState.workFilePath
+       if _, r, ok := replacement(mod, loaderstate.MainModules.WorkFileReplaceMap()); ok {
+               return r, "", loaderstate.workFilePath
        }
-       for _, v := range LoaderState.MainModules.Versions() {
-               if index := LoaderState.MainModules.Index(v); index != nil {
+       for _, v := range loaderstate.MainModules.Versions() {
+               if index := loaderstate.MainModules.Index(v); index != nil {
                        if from, r, ok := replacement(mod, index.replace); ok {
-                               modRoot := LoaderState.MainModules.ModRoot(v)
+                               modRoot := loaderstate.MainModules.ModRoot(v)
                                if foundModRoot != "" && foundFrom != from && found != r {
                                        base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v",
                                                mod, modFilePath(foundModRoot), modFilePath(modRoot))
@@ -376,21 +376,21 @@ func replacementFrom(mod module.Version) (r module.Version, modroot string, from
        return found, foundModRoot, modFilePath(foundModRoot)
 }
 
-func replaceRelativeTo() string {
-       if workFilePath := WorkFilePath(); workFilePath != "" {
+func replaceRelativeTo(loaderstate *State) string {
+       if workFilePath := WorkFilePath(loaderstate); workFilePath != "" {
                return filepath.Dir(workFilePath)
        }
-       return LoaderState.MainModules.ModRoot(LoaderState.MainModules.mustGetSingleMainModule())
+       return loaderstate.MainModules.ModRoot(loaderstate.MainModules.mustGetSingleMainModule(loaderstate))
 }
 
 // canonicalizeReplacePath ensures that relative, on-disk, replaced module paths
 // are relative to the workspace directory (in workspace mode) or to the module's
 // directory (in module mode, as they already are).
-func canonicalizeReplacePath(r module.Version, modRoot string) module.Version {
+func canonicalizeReplacePath(loaderstate *State, r module.Version, modRoot string) module.Version {
        if filepath.IsAbs(r.Path) || r.Version != "" || modRoot == "" {
                return r
        }
-       workFilePath := WorkFilePath()
+       workFilePath := WorkFilePath(loaderstate)
        if workFilePath == "" {
                return r
        }
@@ -407,8 +407,8 @@ func canonicalizeReplacePath(r module.Version, modRoot string) module.Version {
 // for m: either m itself, or the replacement for m (iff m is replaced).
 // It also returns the modroot of the module providing the replacement if
 // one was found.
-func resolveReplacement(m module.Version) module.Version {
-       if r := Replacement(m); r.Path != "" {
+func resolveReplacement(loaderstate *State, m module.Version) module.Version {
+       if r := Replacement(loaderstate, m); r.Path != "" {
                return r
        }
        return m
@@ -573,12 +573,12 @@ type retraction struct {
 // module versions.
 //
 // The caller must not modify the returned summary.
-func goModSummary(m module.Version) (*modFileSummary, error) {
-       if m.Version == "" && !inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) {
+func goModSummary(loaderstate *State, m module.Version) (*modFileSummary, error) {
+       if m.Version == "" && !inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) {
                panic("internal error: goModSummary called on a main module")
        }
        if gover.IsToolchain(m.Path) {
-               return rawGoModSummary(m)
+               return rawGoModSummary(loaderstate, m)
        }
 
        if cfg.BuildMod == "vendor" {
@@ -586,7 +586,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) {
                        module: module.Version{Path: m.Path},
                }
 
-               readVendorList(VendorDir())
+               readVendorList(VendorDir(loaderstate))
                if vendorVersion[m.Path] != m.Version {
                        // This module is not vendored, so packages cannot be loaded from it and
                        // it cannot be relevant to the build.
@@ -601,15 +601,15 @@ func goModSummary(m module.Version) (*modFileSummary, error) {
                return summary, nil
        }
 
-       actual := resolveReplacement(m)
-       if mustHaveSums() && actual.Version != "" {
+       actual := resolveReplacement(loaderstate, m)
+       if mustHaveSums(loaderstate) && actual.Version != "" {
                key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"}
                if !modfetch.HaveSum(key) {
                        suggestion := fmt.Sprintf(" for go.mod file; to add it:\n\tgo mod download %s", m.Path)
                        return nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion})
                }
        }
-       summary, err := rawGoModSummary(actual)
+       summary, err := rawGoModSummary(loaderstate, actual)
        if err != nil {
                return nil, err
        }
@@ -641,8 +641,8 @@ func goModSummary(m module.Version) (*modFileSummary, error) {
                }
        }
 
-       for _, mainModule := range LoaderState.MainModules.Versions() {
-               if index := LoaderState.MainModules.Index(mainModule); index != nil && len(index.exclude) > 0 {
+       for _, mainModule := range loaderstate.MainModules.Versions() {
+               if index := loaderstate.MainModules.Index(mainModule); index != nil && len(index.exclude) > 0 {
                        // Drop any requirements on excluded versions.
                        // Don't modify the cached summary though, since we might need the raw
                        // summary separately.
@@ -676,7 +676,7 @@ func goModSummary(m module.Version) (*modFileSummary, error) {
 // rawGoModSummary cannot be used on the main module outside of workspace mode.
 // The modFileSummary can still be used for retractions and deprecations
 // even if a TooNewError is returned.
-func rawGoModSummary(m module.Version) (*modFileSummary, error) {
+func rawGoModSummary(loaderstate *State, m module.Version) (*modFileSummary, error) {
        if gover.IsToolchain(m.Path) {
                if m.Path == "go" && gover.Compare(m.Version, gover.GoStrictVersion) >= 0 {
                        // Declare that go 1.21.3 requires toolchain 1.21.3,
@@ -686,7 +686,7 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
                }
                return &modFileSummary{module: m}, nil
        }
-       if m.Version == "" && !inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) {
+       if m.Version == "" && !inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) {
                // Calling rawGoModSummary implies that we are treating m as a module whose
                // requirements aren't the roots of the module graph and can't be modified.
                //
@@ -694,22 +694,22 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
                // are the roots of the module graph and we expect them to be kept consistent.
                panic("internal error: rawGoModSummary called on a main module")
        }
-       if m.Version == "" && inWorkspaceMode() && m.Path == "command-line-arguments" {
+       if m.Version == "" && inWorkspaceMode(loaderstate) && m.Path == "command-line-arguments" {
                // "go work sync" calls LoadModGraph to make sure the module graph is valid.
                // If there are no modules in the workspace, we synthesize an empty
                // command-line-arguments module, which rawGoModData cannot read a go.mod for.
                return &modFileSummary{module: m}, nil
-       } else if m.Version == "" && inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) {
+       } else if m.Version == "" && inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) {
                // When go get uses EnterWorkspace to check that the workspace loads properly,
                // it will update the contents of the workspace module's modfile in memory. To use the updated
                // contents of the modfile when doing the load, don't read from disk and instead
                // recompute a summary using the updated contents of the modfile.
-               if mf := LoaderState.MainModules.ModFile(m); mf != nil {
-                       return summaryFromModFile(m, LoaderState.MainModules.modFiles[m])
+               if mf := loaderstate.MainModules.ModFile(m); mf != nil {
+                       return summaryFromModFile(m, loaderstate.MainModules.modFiles[m])
                }
        }
        return rawGoModSummaryCache.Do(m, func() (*modFileSummary, error) {
-               name, data, err := rawGoModData(m)
+               name, data, err := rawGoModData(loaderstate, m)
                if err != nil {
                        return nil, err
                }
@@ -781,15 +781,15 @@ var rawGoModSummaryCache par.ErrCache[module.Version, *modFileSummary]
 //
 // Unlike rawGoModSummary, rawGoModData does not cache its results in memory.
 // Use rawGoModSummary instead unless you specifically need these bytes.
-func rawGoModData(m module.Version) (name string, data []byte, err error) {
+func rawGoModData(loaderstate *State, m module.Version) (name string, data []byte, err error) {
        if m.Version == "" {
                dir := m.Path
                if !filepath.IsAbs(dir) {
-                       if inWorkspaceMode() && LoaderState.MainModules.Contains(m.Path) {
-                               dir = LoaderState.MainModules.ModRoot(m)
+                       if inWorkspaceMode(loaderstate) && loaderstate.MainModules.Contains(m.Path) {
+                               dir = loaderstate.MainModules.ModRoot(m)
                        } else {
                                // m is a replacement module with only a file path.
-                               dir = filepath.Join(replaceRelativeTo(), dir)
+                               dir = filepath.Join(replaceRelativeTo(loaderstate), dir)
                        }
                }
                name = filepath.Join(dir, "go.mod")
@@ -825,12 +825,12 @@ func rawGoModData(m module.Version) (name string, data []byte, err error) {
 //
 // If the queried latest version is replaced,
 // queryLatestVersionIgnoringRetractions returns the replacement.
-func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, err error) {
+func queryLatestVersionIgnoringRetractions(loaderstate *State, ctx context.Context, path string) (latest module.Version, err error) {
        return latestVersionIgnoringRetractionsCache.Do(path, func() (module.Version, error) {
                ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path)
                defer span.Done()
 
-               if repl := Replacement(module.Version{Path: path}); repl.Path != "" {
+               if repl := Replacement(loaderstate, module.Version{Path: path}); repl.Path != "" {
                        // All versions of the module were replaced.
                        // No need to query.
                        return repl, nil
@@ -840,12 +840,12 @@ func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (la
                // Ignore exclusions from the main module's go.mod.
                const ignoreSelected = ""
                var allowAll AllowedFunc
-               rev, err := Query(ctx, path, "latest", ignoreSelected, allowAll)
+               rev, err := Query(loaderstate, ctx, path, "latest", ignoreSelected, allowAll)
                if err != nil {
                        return module.Version{}, err
                }
                latest := module.Version{Path: path, Version: rev.Version}
-               if repl := resolveReplacement(latest); repl.Path != "" {
+               if repl := resolveReplacement(loaderstate, latest); repl.Path != "" {
                        latest = repl
                }
                return latest, nil
index 97e6fe44dd7545bd1b040069bb44cdb2048849ad..32afc866fbcc14fc8d29e3595764d2855e79b9c6 100644 (file)
@@ -53,7 +53,7 @@ func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
                return nil, nil
        }
 
-       summary, err := goModSummary(mod)
+       summary, err := goModSummary(LoaderState, mod)
        if err != nil {
                return nil, err
        }
@@ -79,11 +79,11 @@ func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) {
        return m, nil
 }
 
-func versions(ctx context.Context, path string, allowed AllowedFunc) (versions []string, origin *codehost.Origin, err error) {
+func versions(loaderstate *State, ctx context.Context, path string, allowed AllowedFunc) (versions []string, origin *codehost.Origin, err error) {
        // Note: modfetch.Lookup and repo.Versions are cached,
        // so there's no need for us to add extra caching here.
        err = modfetch.TryProxies(func(proxy string) error {
-               repo, err := lookupRepo(ctx, proxy, path)
+               repo, err := lookupRepo(loaderstate, ctx, proxy, path)
                if err != nil {
                        return err
                }
@@ -111,12 +111,12 @@ func versions(ctx context.Context, path string, allowed AllowedFunc) (versions [
 //
 // Since the version of a main module is not found in the version list,
 // it has no previous version.
-func previousVersion(ctx context.Context, m module.Version) (module.Version, error) {
-       if m.Version == "" && LoaderState.MainModules.Contains(m.Path) {
+func previousVersion(loaderstate *State, ctx context.Context, m module.Version) (module.Version, error) {
+       if m.Version == "" && loaderstate.MainModules.Contains(m.Path) {
                return module.Version{Path: m.Path, Version: "none"}, nil
        }
 
-       list, _, err := versions(ctx, m.Path, CheckAllowed)
+       list, _, err := versions(loaderstate, ctx, m.Path, CheckAllowed)
        if err != nil {
                if errors.Is(err, os.ErrNotExist) {
                        return module.Version{Path: m.Path, Version: "none"}, nil
@@ -132,5 +132,5 @@ func previousVersion(ctx context.Context, m module.Version) (module.Version, err
 
 func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
        // TODO(golang.org/issue/38714): thread tracing context through MVS.
-       return previousVersion(context.TODO(), m)
+       return previousVersion(LoaderState, context.TODO(), m)
 }
index b37a244fbbacddb356d45e1bfa8cc2f58c8a448f..17a0aef21ab2e9f0a8d66d034275d331f74b75a3 100644 (file)
@@ -80,19 +80,19 @@ import (
 //
 // Query often returns a non-nil *RevInfo with a non-nil error,
 // to provide an info.Origin that can allow the error to be cached.
-func Query(ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) {
+func Query(loaderstate *State, ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) {
        ctx, span := trace.StartSpan(ctx, "modload.Query "+path)
        defer span.Done()
 
-       return queryReuse(ctx, path, query, current, allowed, nil)
+       return queryReuse(loaderstate, ctx, path, query, current, allowed, nil)
 }
 
 // queryReuse is like Query but also takes a map of module info that can be reused
 // if the validation criteria in Origin are met.
-func queryReuse(ctx context.Context, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) {
+func queryReuse(loaderstate *State, ctx context.Context, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) {
        var info *modfetch.RevInfo
        err := modfetch.TryProxies(func(proxy string) (err error) {
-               info, err = queryProxy(ctx, proxy, path, query, current, allowed, reuse)
+               info, err = queryProxy(loaderstate, ctx, proxy, path, query, current, allowed, reuse)
                return err
        })
        return info, err
@@ -100,9 +100,9 @@ func queryReuse(ctx context.Context, path, query, current string, allowed Allowe
 
 // checkReuse checks whether a revision of a given module
 // for a given module may be reused, according to the information in origin.
-func checkReuse(ctx context.Context, m module.Version, old *codehost.Origin) error {
+func checkReuse(loaderstate *State, ctx context.Context, m module.Version, old *codehost.Origin) error {
        return modfetch.TryProxies(func(proxy string) error {
-               repo, err := lookupRepo(ctx, proxy, m.Path)
+               repo, err := lookupRepo(loaderstate, ctx, proxy, m.Path)
                if err != nil {
                        return err
                }
@@ -197,7 +197,7 @@ func (queryDisabledError) Error() string {
        return fmt.Sprintf("cannot query module due to -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
 }
 
-func queryProxy(ctx context.Context, proxy, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) {
+func queryProxy(loaderstate *State, ctx context.Context, proxy, path, query, current string, allowed AllowedFunc, reuse map[module.Version]*modinfo.ModulePublic) (*modfetch.RevInfo, error) {
        ctx, span := trace.StartSpan(ctx, "modload.queryProxy "+path+" "+query)
        defer span.Done()
 
@@ -211,7 +211,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
                allowed = func(context.Context, module.Version) error { return nil }
        }
 
-       if LoaderState.MainModules.Contains(path) && (query == "upgrade" || query == "patch") {
+       if loaderstate.MainModules.Contains(path) && (query == "upgrade" || query == "patch") {
                m := module.Version{Path: path}
                if err := allowed(ctx, m); err != nil {
                        return nil, fmt.Errorf("internal error: main module version is not allowed: %w", err)
@@ -223,7 +223,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
                return nil, fmt.Errorf("can't query specific version (%q) of standard-library module %q", query, path)
        }
 
-       repo, err := lookupRepo(ctx, proxy, path)
+       repo, err := lookupRepo(loaderstate, ctx, proxy, path)
        if err != nil {
                return nil, err
        }
@@ -296,7 +296,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed
                return &clone
        }
 
-       releases, prereleases, err := qm.filterVersions(ctx, versions.List)
+       releases, prereleases, err := qm.filterVersions(loaderstate, ctx, versions.List)
        if err != nil {
                return revWithOrigin(nil), err
        }
@@ -569,7 +569,7 @@ func (qm *queryMatcher) allowsVersion(ctx context.Context, v string) bool {
 //
 // If the allowed predicate returns an error not equivalent to ErrDisallowed,
 // filterVersions returns that error.
-func (qm *queryMatcher) filterVersions(ctx context.Context, versions []string) (releases, prereleases []string, err error) {
+func (qm *queryMatcher) filterVersions(loaderstate *State, ctx context.Context, versions []string) (releases, prereleases []string, err error) {
        needIncompatible := qm.preferIncompatible
 
        var lastCompatible string
@@ -602,7 +602,7 @@ func (qm *queryMatcher) filterVersions(ctx context.Context, versions []string) (
                                // ignore any version with a higher (+incompatible) major version. (See
                                // https://golang.org/issue/34165.) Note that we even prefer a
                                // compatible pre-release over an incompatible release.
-                               ok, err := versionHasGoMod(ctx, module.Version{Path: qm.path, Version: lastCompatible})
+                               ok, err := versionHasGoMod(loaderstate, ctx, module.Version{Path: qm.path, Version: lastCompatible})
                                if err != nil {
                                        return nil, nil, err
                                }
@@ -639,11 +639,11 @@ type QueryResult struct {
 
 // QueryPackages is like QueryPattern, but requires that the pattern match at
 // least one package and omits the non-package result (if any).
-func QueryPackages(ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) ([]QueryResult, error) {
-       pkgMods, modOnly, err := QueryPattern(ctx, pattern, query, current, allowed)
+func QueryPackages(loaderstate *State, ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) ([]QueryResult, error) {
+       pkgMods, modOnly, err := QueryPattern(loaderstate, ctx, pattern, query, current, allowed)
 
        if len(pkgMods) == 0 && err == nil {
-               replacement := Replacement(modOnly.Mod)
+               replacement := Replacement(loaderstate, modOnly.Mod)
                return nil, &PackageNotInModuleError{
                        Mod:         modOnly.Mod,
                        Replacement: replacement,
@@ -670,7 +670,7 @@ func QueryPackages(ctx context.Context, pattern, query string, current func(stri
 //
 // QueryPattern always returns at least one QueryResult (which may be only
 // modOnly) or a non-nil error.
-func QueryPattern(ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) (pkgMods []QueryResult, modOnly *QueryResult, err error) {
+func QueryPattern(loaderstate *State, ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) (pkgMods []QueryResult, modOnly *QueryResult, err error) {
        ctx, span := trace.StartSpan(ctx, "modload.QueryPattern "+pattern+" "+query)
        defer span.Done()
 
@@ -693,15 +693,15 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
                }
                match = func(mod module.Version, roots []string, isLocal bool) *search.Match {
                        m := search.NewMatch(pattern)
-                       matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{mod})
+                       matchPackages(loaderstate, ctx, m, imports.AnyTags(), omitStd, []module.Version{mod})
                        return m
                }
        } else {
                match = func(mod module.Version, roots []string, isLocal bool) *search.Match {
                        m := search.NewMatch(pattern)
                        prefix := mod.Path
-                       if LoaderState.MainModules.Contains(mod.Path) {
-                               prefix = LoaderState.MainModules.PathPrefix(module.Version{Path: mod.Path})
+                       if loaderstate.MainModules.Contains(mod.Path) {
+                               prefix = loaderstate.MainModules.PathPrefix(module.Version{Path: mod.Path})
                        }
                        for _, root := range roots {
                                if _, ok, err := dirInModule(pattern, prefix, root, isLocal); err != nil {
@@ -715,8 +715,8 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
        }
 
        var mainModuleMatches []module.Version
-       for _, mainModule := range LoaderState.MainModules.Versions() {
-               m := match(mainModule, LoaderState.modRoots, true)
+       for _, mainModule := range loaderstate.MainModules.Versions() {
+               m := match(mainModule, loaderstate.modRoots, true)
                if len(m.Pkgs) > 0 {
                        if query != "upgrade" && query != "patch" {
                                return nil, nil, &QueryMatchesPackagesInMainModuleError{
@@ -756,7 +756,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
 
        var (
                results          []QueryResult
-               candidateModules = modulePrefixesExcludingTarget(base)
+               candidateModules = modulePrefixesExcludingTarget(loaderstate, base)
        )
        if len(candidateModules) == 0 {
                if modOnly != nil {
@@ -783,7 +783,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
 
                        pathCurrent := current(path)
                        r.Mod.Path = path
-                       r.Rev, err = queryProxy(ctx, proxy, path, query, pathCurrent, allowed, nil)
+                       r.Rev, err = queryProxy(loaderstate, ctx, proxy, path, query, pathCurrent, allowed, nil)
                        if err != nil {
                                return r, err
                        }
@@ -791,7 +791,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
                        if gover.IsToolchain(r.Mod.Path) {
                                return r, nil
                        }
-                       root, isLocal, err := fetch(ctx, r.Mod)
+                       root, isLocal, err := fetch(loaderstate, ctx, r.Mod)
                        if err != nil {
                                return r, err
                        }
@@ -801,7 +801,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
                                if err := firstError(m); err != nil {
                                        return r, err
                                }
-                               replacement := Replacement(r.Mod)
+                               replacement := Replacement(loaderstate, r.Mod)
                                return r, &PackageNotInModuleError{
                                        Mod:         r.Mod,
                                        Replacement: replacement,
@@ -812,7 +812,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
                        return r, nil
                }
 
-               allResults, err := queryPrefixModules(ctx, candidateModules, queryModule)
+               allResults, err := queryPrefixModules(loaderstate, ctx, candidateModules, queryModule)
                results = allResults[:0]
                for _, r := range allResults {
                        if len(r.Packages) == 0 {
@@ -838,11 +838,11 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
 // itself, sorted by descending length. Prefixes that are not valid module paths
 // but are valid package paths (like "m" or "example.com/.gen") are included,
 // since they might be replaced.
-func modulePrefixesExcludingTarget(path string) []string {
+func modulePrefixesExcludingTarget(loaderstate *State, path string) []string {
        prefixes := make([]string, 0, strings.Count(path, "/")+1)
 
        mainModulePrefixes := make(map[string]bool)
-       for _, m := range LoaderState.MainModules.Versions() {
+       for _, m := range loaderstate.MainModules.Versions() {
                mainModulePrefixes[m.Path] = true
        }
 
@@ -863,7 +863,7 @@ func modulePrefixesExcludingTarget(path string) []string {
        return prefixes
 }
 
-func queryPrefixModules(ctx context.Context, candidateModules []string, queryModule func(ctx context.Context, path string) (QueryResult, error)) (found []QueryResult, err error) {
+func queryPrefixModules(loaderstate *State, ctx context.Context, candidateModules []string, queryModule func(ctx context.Context, path string) (QueryResult, error)) (found []QueryResult, err error) {
        ctx, span := trace.StartSpan(ctx, "modload.queryPrefixModules")
        defer span.Done()
 
@@ -905,7 +905,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
                case *PackageNotInModuleError:
                        // Given the option, prefer to attribute “package not in module”
                        // to modules other than the main one.
-                       if noPackage == nil || LoaderState.MainModules.Contains(noPackage.Mod.Path) {
+                       if noPackage == nil || loaderstate.MainModules.Contains(noPackage.Mod.Path) {
                                noPackage = rErr
                        }
                case *NoMatchingVersionError:
@@ -1096,8 +1096,8 @@ func (e *PackageNotInModuleError) ImportPath() string {
 // go.mod with different content. Second, if we don't fetch the .zip, then
 // we don't need to verify it in go.sum. This makes 'go list -m -u' faster
 // and simpler.
-func versionHasGoMod(_ context.Context, m module.Version) (bool, error) {
-       _, data, err := rawGoModData(m)
+func versionHasGoMod(loaderstate *State, _ context.Context, m module.Version) (bool, error) {
+       _, data, err := rawGoModData(loaderstate, m)
        if err != nil {
                return false, err
        }
@@ -1117,7 +1117,7 @@ type versionRepo interface {
 
 var _ versionRepo = modfetch.Repo(nil)
 
-func lookupRepo(ctx context.Context, proxy, path string) (repo versionRepo, err error) {
+func lookupRepo(loaderstate *State, ctx context.Context, proxy, path string) (repo versionRepo, err error) {
        if path != "go" && path != "toolchain" {
                err = module.CheckPath(path)
        }
@@ -1127,9 +1127,9 @@ func lookupRepo(ctx context.Context, proxy, path string) (repo versionRepo, err
                repo = emptyRepo{path: path, err: err}
        }
 
-       if LoaderState.MainModules == nil {
+       if loaderstate.MainModules == nil {
                return repo, err
-       } else if _, ok := LoaderState.MainModules.HighestReplaced()[path]; ok {
+       } else if _, ok := loaderstate.MainModules.HighestReplaced()[path]; ok {
                return &replacementRepo{repo: repo}, nil
        }
 
@@ -1239,7 +1239,7 @@ func (rr *replacementRepo) Stat(ctx context.Context, rev string) (*modfetch.RevI
                }
        }
 
-       if r := Replacement(module.Version{Path: path, Version: v}); r.Path == "" {
+       if r := Replacement(LoaderState, module.Version{Path: path, Version: v}); r.Path == "" {
                return info, err
        }
        return rr.replacementStat(v)
index 93f8f0d00d1c8d9756d485e97fe87116a56d575d..b4487eebb0d9e957f23c250e24fd68b3b62d888c 100644 (file)
@@ -182,7 +182,7 @@ func TestQuery(t *testing.T) {
                t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+tt.current+"/"+allow, func(t *testing.T) {
                        t.Parallel()
 
-                       info, err := Query(ctx, tt.path, tt.query, tt.current, allowed)
+                       info, err := Query(LoaderState, ctx, tt.path, tt.query, tt.current, allowed)
                        if tt.err != "" {
                                if err == nil {
                                        t.Errorf("Query(_, %q, %q, %q, %v) = %v, want error %q", tt.path, tt.query, tt.current, allow, info.Version, tt.err)
index 205db3e8f7c8db2ddea64144774bea63161986d5..9951e68ee8e6c9e5eb06242f78c727d6a6966dea 100644 (file)
@@ -41,7 +41,7 @@ const (
 // matchPackages is like m.MatchPackages, but uses a local variable (rather than
 // a global) for tags, can include or exclude packages in the standard library,
 // and is restricted to the given list of modules.
-func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) {
+func matchPackages(loaderstate *State, ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) {
        ctx, span := trace.StartSpan(ctx, "modload.matchPackages")
        defer span.Done()
 
@@ -74,7 +74,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
        )
 
        q := par.NewQueue(runtime.GOMAXPROCS(0))
-       ignorePatternsMap := parseIgnorePatterns(ctx, treeCanMatch, modules)
+       ignorePatternsMap := parseIgnorePatterns(loaderstate, ctx, treeCanMatch, modules)
        walkPkgs := func(root, importPathRoot string, prune pruning) {
                _, span := trace.StartSpan(ctx, "walkPkgs "+root)
                defer span.Done()
@@ -171,13 +171,13 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
        }
 
        if cfg.BuildMod == "vendor" {
-               for _, mod := range LoaderState.MainModules.Versions() {
-                       if modRoot := LoaderState.MainModules.ModRoot(mod); modRoot != "" {
-                               walkPkgs(modRoot, LoaderState.MainModules.PathPrefix(mod), pruneGoMod|pruneVendor)
+               for _, mod := range loaderstate.MainModules.Versions() {
+                       if modRoot := loaderstate.MainModules.ModRoot(mod); modRoot != "" {
+                               walkPkgs(modRoot, loaderstate.MainModules.PathPrefix(mod), pruneGoMod|pruneVendor)
                        }
                }
-               if HasModRoot() {
-                       walkPkgs(VendorDir(), "", pruneVendor)
+               if HasModRoot(loaderstate) {
+                       walkPkgs(VendorDir(loaderstate), "", pruneVendor)
                }
                return
        }
@@ -191,16 +191,16 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
                        root, modPrefix string
                        isLocal         bool
                )
-               if LoaderState.MainModules.Contains(mod.Path) {
-                       if LoaderState.MainModules.ModRoot(mod) == "" {
+               if loaderstate.MainModules.Contains(mod.Path) {
+                       if loaderstate.MainModules.ModRoot(mod) == "" {
                                continue // If there is no main module, we can't search in it.
                        }
-                       root = LoaderState.MainModules.ModRoot(mod)
-                       modPrefix = LoaderState.MainModules.PathPrefix(mod)
+                       root = loaderstate.MainModules.ModRoot(mod)
+                       modPrefix = loaderstate.MainModules.PathPrefix(mod)
                        isLocal = true
                } else {
                        var err error
-                       root, isLocal, err = fetch(ctx, mod)
+                       root, isLocal, err = fetch(loaderstate, ctx, mod)
                        if err != nil {
                                m.AddError(err)
                                continue
@@ -286,17 +286,17 @@ func walkFromIndex(index *modindex.Module, importPathRoot string, isMatch, treeC
 func MatchInModule(ctx context.Context, pattern string, m module.Version, tags map[string]bool) *search.Match {
        match := search.NewMatch(pattern)
        if m == (module.Version{}) {
-               matchPackages(ctx, match, tags, includeStd, nil)
+               matchPackages(LoaderState, ctx, match, tags, includeStd, nil)
        }
 
-       LoadModFile(ctx) // Sets Target, needed by fetch and matchPackages.
+       LoadModFile(LoaderState, ctx) // Sets Target, needed by fetch and matchPackages.
 
        if !match.IsLiteral() {
-               matchPackages(ctx, match, tags, omitStd, []module.Version{m})
+               matchPackages(LoaderState, ctx, match, tags, omitStd, []module.Version{m})
                return match
        }
 
-       root, isLocal, err := fetch(ctx, m)
+       root, isLocal, err := fetch(LoaderState, ctx, m)
        if err != nil {
                match.Errs = []error{err}
                return match
@@ -322,7 +322,7 @@ func MatchInModule(ctx context.Context, pattern string, m module.Version, tags m
 // parseIgnorePatterns collects all ignore patterns associated with the
 // provided list of modules.
 // It returns a map of module root -> *search.IgnorePatterns.
-func parseIgnorePatterns(ctx context.Context, treeCanMatch func(string) bool, modules []module.Version) map[string]*search.IgnorePatterns {
+func parseIgnorePatterns(loaderstate *State, ctx context.Context, treeCanMatch func(string) bool, modules []module.Version) map[string]*search.IgnorePatterns {
        ignorePatternsMap := make(map[string]*search.IgnorePatterns)
        for _, mod := range modules {
                if gover.IsToolchain(mod.Path) || !treeCanMatch(mod.Path) {
@@ -330,12 +330,12 @@ func parseIgnorePatterns(ctx context.Context, treeCanMatch func(string) bool, mo
                }
                var modRoot string
                var ignorePatterns []string
-               if LoaderState.MainModules.Contains(mod.Path) {
-                       modRoot = LoaderState.MainModules.ModRoot(mod)
+               if loaderstate.MainModules.Contains(mod.Path) {
+                       modRoot = loaderstate.MainModules.ModRoot(mod)
                        if modRoot == "" {
                                continue
                        }
-                       modIndex := LoaderState.MainModules.Index(mod)
+                       modIndex := loaderstate.MainModules.Index(mod)
                        if modIndex == nil {
                                continue
                        }
@@ -344,11 +344,11 @@ func parseIgnorePatterns(ctx context.Context, treeCanMatch func(string) bool, mo
                        // Skip getting ignore patterns for vendored modules because they
                        // do not have go.mod files.
                        var err error
-                       modRoot, _, err = fetch(ctx, mod)
+                       modRoot, _, err = fetch(loaderstate, ctx, mod)
                        if err != nil {
                                continue
                        }
-                       summary, err := goModSummary(mod)
+                       summary, err := goModSummary(loaderstate, mod)
                        if err != nil {
                                continue
                        }
index d3f055acf64f502a6dba503ee7d7348a2f599542..bf0c4e403717a6e6600fbb4d778ea710d6b8109a 100644 (file)
@@ -140,10 +140,10 @@ func readVendorList(vendorDir string) {
 // checkVendorConsistency verifies that the vendor/modules.txt file matches (if
 // go 1.14) or at least does not contradict (go 1.13 or earlier) the
 // requirements and replacements listed in the main module's go.mod file.
-func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, modRoots []string) {
+func checkVendorConsistency(loaderstate *State, indexes []*modFileIndex, modFiles []*modfile.File, modRoots []string) {
        // readVendorList only needs the main module to get the directory
        // the vendor directory is in.
-       readVendorList(VendorDir())
+       readVendorList(VendorDir(loaderstate))
 
        if len(modFiles) < 1 {
                // We should never get here if there are zero modfiles. Either
@@ -154,7 +154,7 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m
        }
 
        pre114 := false
-       if !inWorkspaceMode() { // workspace mode was added after Go 1.14
+       if !inWorkspaceMode(loaderstate) { // workspace mode was added after Go 1.14
                if len(indexes) != 1 {
                        panic(fmt.Errorf("not in workspace mode but number of indexes is %v, not 1", len(indexes)))
                }
@@ -215,8 +215,8 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m
                                continue // Don't print the same error more than once
                        }
                        seenrep[r.Old] = true
-                       rNew, modRoot, replacementSource := replacementFrom(r.Old)
-                       rNewCanonical := canonicalizeReplacePath(rNew, modRoot)
+                       rNew, modRoot, replacementSource := replacementFrom(loaderstate, r.Old)
+                       rNewCanonical := canonicalizeReplacePath(loaderstate, rNew, modRoot)
                        vr := vendorMeta[r.Old].Replacement
                        if vr == (module.Version{}) {
                                if rNewCanonical == (module.Version{}) {
@@ -236,8 +236,8 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m
        for _, modFile := range modFiles {
                checkReplace(modFile.Replace)
        }
-       if LoaderState.MainModules.workFile != nil {
-               checkReplace(LoaderState.MainModules.workFile.Replace)
+       if loaderstate.MainModules.workFile != nil {
+               checkReplace(loaderstate.MainModules.workFile.Replace)
        }
 
        for _, mod := range vendorList {
@@ -252,7 +252,7 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m
                        }
                        if !foundRequire {
                                article := ""
-                               if inWorkspaceMode() {
+                               if inWorkspaceMode(loaderstate) {
                                        article = "a "
                                }
                                vendErrorf(mod, "is marked as explicit in vendor/modules.txt, but not explicitly required in %vgo.mod", article)
@@ -262,9 +262,9 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m
        }
 
        for _, mod := range vendorReplaced {
-               r := Replacement(mod)
+               r := Replacement(loaderstate, mod)
                replacementSource := "go.mod"
-               if inWorkspaceMode() {
+               if inWorkspaceMode(loaderstate) {
                        replacementSource = "the workspace"
                }
                if r == (module.Version{}) {
@@ -276,9 +276,9 @@ func checkVendorConsistency(indexes []*modFileIndex, modFiles []*modfile.File, m
 
        if vendErrors.Len() > 0 {
                subcmd := "mod"
-               if inWorkspaceMode() {
+               if inWorkspaceMode(loaderstate) {
                        subcmd = "work"
                }
-               base.Fatalf("go: inconsistent vendoring in %s:%s\n\n\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo %s vendor", filepath.Dir(VendorDir()), vendErrors, subcmd)
+               base.Fatalf("go: inconsistent vendoring in %s:%s\n\n\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo %s vendor", filepath.Dir(VendorDir(loaderstate)), vendErrors, subcmd)
        }
 }
index d922dcdd66a551d34fb8ac6f0fce48b237434417..b6d76514b032d8a0353b9c4eafd0d41316cf3834 100644 (file)
@@ -78,13 +78,13 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
                // for -race and -msan.
                modload.LoaderState.ForceUseModules = true
                modload.LoaderState.RootMode = modload.NoRoot
-               modload.AllowMissingModuleImports()
-               modload.Init()
+               modload.AllowMissingModuleImports(modload.LoaderState)
+               modload.Init(modload.LoaderState)
        } else {
-               modload.InitWorkfile()
+               modload.InitWorkfile(modload.LoaderState)
        }
 
-       work.BuildInit()
+       work.BuildInit(modload.LoaderState)
        b := work.NewBuilder("")
        defer func() {
                if err := b.Close(); err != nil {
@@ -107,18 +107,18 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
                                base.Fatalf("go: cannot run *_test.go files (%s)", file)
                        }
                }
-               p = load.GoFilesPackage(ctx, pkgOpts, files)
+               p = load.GoFilesPackage(modload.LoaderState, ctx, pkgOpts, files)
        } else if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
                arg := args[0]
                var pkgs []*load.Package
                if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) {
                        var err error
-                       pkgs, err = load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args[:1])
+                       pkgs, err = load.PackagesAndErrorsOutsideModule(modload.LoaderState, ctx, pkgOpts, args[:1])
                        if err != nil {
                                base.Fatal(err)
                        }
                } else {
-                       pkgs = load.PackagesAndErrors(ctx, pkgOpts, args[:1])
+                       pkgs = load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, args[:1])
                }
 
                if len(pkgs) == 0 {
@@ -140,7 +140,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
        load.CheckPackageErrors([]*load.Package{p})
 
        if cfg.BuildCover {
-               load.PrepareForCoverageBuild([]*load.Package{p})
+               load.PrepareForCoverageBuild(modload.LoaderState, []*load.Package{p})
        }
 
        p.Internal.OmitDebug = true
@@ -166,7 +166,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
                p.Internal.ExeName = p.DefaultExecName()
        }
 
-       a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p)
+       a1 := b.LinkAction(modload.LoaderState, work.ModeBuild, work.ModeBuild, p)
        a1.CacheExecutable = true
        a := &work.Action{Mode: "go run", Actor: work.ActorFunc(buildRunProgram), Args: cmdArgs, Deps: []*work.Action{a1}}
        b.Do(ctx, a)
index d5b642240f16b7a3d3bccf9157b3d512f1e8e590..9586324551dfc95b80d151d938c39195331ec778 100644 (file)
@@ -24,7 +24,7 @@ func Increment() {
 func incrementConfig() {
        if !modload.WillBeEnabled() {
                counter.Inc("go/mode:gopath")
-       } else if workfile := modload.FindGoWork(base.Cwd()); workfile != "" {
+       } else if workfile := modload.FindGoWork(modload.LoaderState, base.Cwd()); workfile != "" {
                counter.Inc("go/mode:workspace")
        } else {
                counter.Inc("go/mode:module")
index e225929add20c2c692e2062ec5d67afe9e648b66..5e5d79a39f001fe062e9f81991b6d05b2ce4f18e 100644 (file)
@@ -683,7 +683,7 @@ var defaultVetFlags = []string{
 
 func runTest(ctx context.Context, cmd *base.Command, args []string) {
        pkgArgs, testArgs = testFlags(args)
-       modload.InitWorkfile() // The test command does custom flag processing; initialize workspaces after that.
+       modload.InitWorkfile(modload.LoaderState) // The test command does custom flag processing; initialize workspaces after that.
 
        if cfg.DebugTrace != "" {
                var close func() error
@@ -704,13 +704,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
 
        work.FindExecCmd() // initialize cached result
 
-       work.BuildInit()
+       work.BuildInit(modload.LoaderState)
        work.VetFlags = testVet.flags
        work.VetExplicit = testVet.explicit
        work.VetTool = base.Tool("vet")
 
        pkgOpts := load.PackageOpts{ModResolveTests: true}
-       pkgs = load.PackagesAndErrors(ctx, pkgOpts, pkgArgs)
+       pkgs = load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, pkgArgs)
        // We *don't* call load.CheckPackageErrors here because we want to report
        // loading errors as per-package test setup errors later.
        if len(pkgs) == 0 {
@@ -741,7 +741,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
                        if !mainMods.Contains(m.Path) {
                                base.Fatalf("cannot use -fuzz flag on package outside the main module")
                        }
-               } else if pkgs[0].Standard && modload.Enabled() {
+               } else if pkgs[0].Standard && modload.Enabled(modload.LoaderState) {
                        // Because packages in 'std' and 'cmd' are part of the standard library,
                        // they are only treated as part of a module in 'go mod' subcommands and
                        // 'go get'. However, we still don't want to accidentally corrupt their
@@ -867,13 +867,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
        if cfg.BuildCoverPkg != nil {
                match := make([]func(*load.Package) bool, len(cfg.BuildCoverPkg))
                for i := range cfg.BuildCoverPkg {
-                       match[i] = load.MatchPackage(cfg.BuildCoverPkg[i], base.Cwd())
+                       match[i] = load.MatchPackage(modload.LoaderState, cfg.BuildCoverPkg[i], base.Cwd())
                }
 
                // Select for coverage all dependencies matching the -coverpkg
                // patterns.
                plist := load.TestPackageList(ctx, pkgOpts, pkgs)
-               testCoverPkgs = load.SelectCoverPackages(plist, match, "test")
+               testCoverPkgs = load.SelectCoverPackages(modload.LoaderState, plist, match, "test")
                if len(testCoverPkgs) > 0 {
                        // create a new singleton action that will collect up the
                        // meta-data files from all of the packages mentioned in
@@ -981,7 +981,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
                        // happens we'll wind up building the Q compile action
                        // before updating its deps to include sync/atomic).
                        if cfg.BuildCoverMode == "atomic" && p.ImportPath != "sync/atomic" {
-                               load.EnsureImport(p, "sync/atomic")
+                               load.EnsureImport(modload.LoaderState, p, "sync/atomic")
                        }
                        // Tag the package for static meta-data generation if no
                        // test files (this works only with the new coverage
@@ -1221,7 +1221,7 @@ func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts,
                }
        }
 
-       a := b.LinkAction(work.ModeBuild, work.ModeBuild, pmain)
+       a := b.LinkAction(modload.LoaderState, work.ModeBuild, work.ModeBuild, pmain)
        a.Target = testDir + testBinary + cfg.ExeSuffix
        if cfg.Goos == "windows" {
                // There are many reserved words on Windows that,
index e25c06a8f046bd8d3520b075afb529f66e50a4fe..e95b07d8c813aa99cae4cf6437b195ab59aa1d07 100644 (file)
@@ -161,8 +161,8 @@ func listTools(ctx context.Context) {
                fmt.Println(name)
        }
 
-       modload.InitWorkfile()
-       modload.LoadModFile(ctx)
+       modload.InitWorkfile(modload.LoaderState)
+       modload.LoadModFile(modload.LoaderState, ctx)
        modTools := slices.Sorted(maps.Keys(modload.LoaderState.MainModules.Tools()))
        for _, tool := range modTools {
                fmt.Println(tool)
@@ -252,8 +252,8 @@ func loadBuiltinTool(toolName string) string {
 }
 
 func loadModTool(ctx context.Context, name string) string {
-       modload.InitWorkfile()
-       modload.LoadModFile(ctx)
+       modload.InitWorkfile(modload.LoaderState)
+       modload.LoadModFile(modload.LoaderState, ctx)
 
        matches := []string{}
        for tool := range modload.LoaderState.MainModules.Tools() {
@@ -336,7 +336,7 @@ func buildAndRunModtool(ctx context.Context, toolName, tool string, args []strin
 }
 
 func buildAndRunTool(ctx context.Context, tool string, args []string, runTool work.ActorFunc) {
-       work.BuildInit()
+       work.BuildInit(modload.LoaderState)
        b := work.NewBuilder("")
        defer func() {
                if err := b.Close(); err != nil {
@@ -345,11 +345,11 @@ func buildAndRunTool(ctx context.Context, tool string, args []string, runTool wo
        }()
 
        pkgOpts := load.PackageOpts{MainOnly: true}
-       p := load.PackagesAndErrors(ctx, pkgOpts, []string{tool})[0]
+       p := load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, []string{tool})[0]
        p.Internal.OmitDebug = true
        p.Internal.ExeName = p.DefaultExecName()
 
-       a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p)
+       a1 := b.LinkAction(modload.LoaderState, work.ModeBuild, work.ModeBuild, p)
        a1.CacheExecutable = true
        a := &work.Action{Mode: "go tool", Actor: runTool, Args: args, Deps: []*work.Action{a1}}
        b.Do(ctx, a)
index 4f46b19c12167b1758040aee924bdc17be8c943d..d54277ed1b4beafc71d16429a44c960e35deca98 100644 (file)
@@ -355,7 +355,7 @@ func Exec(gotoolchain string) {
        modload.Reset()
        modload.LoaderState.ForceUseModules = true
        modload.LoaderState.RootMode = modload.NoRoot
-       modload.Init()
+       modload.Init(modload.LoaderState)
 
        // Download and unpack toolchain module into module cache.
        // Note that multiple go commands might be doing this at the same time,
@@ -529,7 +529,7 @@ func raceSafeCopy(old, new string) error {
 // The toolchain line overrides the version line
 func modGoToolchain() (file, goVers, toolchain string) {
        wd := base.UncachedCwd()
-       file = modload.FindGoWork(wd)
+       file = modload.FindGoWork(modload.LoaderState, wd)
        // $GOWORK can be set to a file that does not yet exist, if we are running 'go work init'.
        // Do not try to load the file in that case
        if _, err := os.Stat(file); err != nil {
@@ -694,7 +694,7 @@ func maybeSwitchForGoInstallVersion(minVers string) {
        // Set up modules without an explicit go.mod, to download go.mod.
        modload.LoaderState.ForceUseModules = true
        modload.LoaderState.RootMode = modload.NoRoot
-       modload.Init()
+       modload.Init(modload.LoaderState)
        defer modload.Reset()
 
        // See internal/load.PackagesAndErrorsOutsideModule
@@ -705,7 +705,7 @@ func maybeSwitchForGoInstallVersion(minVers string) {
                allowed = nil
        }
        noneSelected := func(path string) (version string) { return "none" }
-       _, err := modload.QueryPackages(ctx, path, version, noneSelected, allowed)
+       _, err := modload.QueryPackages(modload.LoaderState, ctx, path, version, noneSelected, allowed)
        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.
index a2625b21188cf48532bfbaf53a9f077e515b9974..e274348bd6a38ea6a76709e5925a7ab5a86e4d09 100644 (file)
@@ -123,7 +123,7 @@ func run(ctx context.Context, cmd *base.Command, args []string) {
 
        // The vet/fix commands do custom flag processing;
        // initialize workspaces after that.
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
 
        if cfg.DebugTrace != "" {
                var close func() error
@@ -142,7 +142,7 @@ func run(ctx context.Context, cmd *base.Command, args []string) {
        ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
        defer span.Done()
 
-       work.BuildInit()
+       work.BuildInit(modload.LoaderState)
 
        // Flag theory:
        //
@@ -217,7 +217,7 @@ func run(ctx context.Context, cmd *base.Command, args []string) {
        work.VetFlags = toolFlags
 
        pkgOpts := load.PackageOpts{ModResolveTests: true}
-       pkgs := load.PackagesAndErrors(ctx, pkgOpts, pkgArgs)
+       pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, pkgOpts, pkgArgs)
        load.CheckPackageErrors(pkgs)
        if len(pkgs) == 0 {
                base.Fatalf("no packages to %s", cmd.Name())
index 3636f642e26401899e2f380b792e2c5c89d0ab99..f1f3bcea38d9d5feb6c79a426073437c9e2ad715 100644 (file)
@@ -28,6 +28,7 @@ import (
        "cmd/go/internal/cache"
        "cmd/go/internal/cfg"
        "cmd/go/internal/load"
+       "cmd/go/internal/modload"
        "cmd/go/internal/str"
        "cmd/go/internal/trace"
        "cmd/internal/buildid"
@@ -392,7 +393,7 @@ func (b *Builder) NewObjdir() string {
 // at shlibpath. For the native toolchain this list is stored, newline separated, in
 // an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
 // .go_export section.
-func readpkglist(shlibpath string) (pkgs []*load.Package) {
+func readpkglist(loaderstate *modload.State, shlibpath string) (pkgs []*load.Package) {
        var stk load.ImportStack
        if cfg.BuildToolchainName == "gccgo" {
                f, err := elf.Open(shlibpath)
@@ -412,7 +413,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) {
                for _, line := range bytes.Split(data, []byte{'\n'}) {
                        if path, found := bytes.CutPrefix(line, pkgpath); found {
                                path = bytes.TrimSuffix(path, []byte{';'})
-                               pkgs = append(pkgs, load.LoadPackageWithFlags(string(path), base.Cwd(), &stk, nil, 0))
+                               pkgs = append(pkgs, load.LoadPackageWithFlags(loaderstate, string(path), base.Cwd(), &stk, nil, 0))
                        }
                }
        } else {
@@ -423,7 +424,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) {
                scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
                for scanner.Scan() {
                        t := scanner.Text()
-                       pkgs = append(pkgs, load.LoadPackageWithFlags(t, base.Cwd(), &stk, nil, 0))
+                       pkgs = append(pkgs, load.LoadPackageWithFlags(loaderstate, t, base.Cwd(), &stk, nil, 0))
                }
        }
        return
@@ -445,7 +446,7 @@ func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *A
 // AutoAction returns the "right" action for go build or go install of p.
 func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action {
        if p.Name == "main" {
-               return b.LinkAction(mode, depMode, p)
+               return b.LinkAction(modload.LoaderState, mode, depMode, p)
        }
        return b.CompileAction(mode, depMode, p)
 }
@@ -913,7 +914,7 @@ func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action {
 // LinkAction returns the action for linking p into an executable
 // and possibly installing the result (according to mode).
 // depMode is the action (build or install) to use when compiling dependencies.
-func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action {
+func (b *Builder) LinkAction(loaderstate *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
        // Construct link action.
        a := b.cacheAction("link", p, func() *Action {
                a := &Action{
@@ -948,7 +949,7 @@ func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action {
                }
                a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
                a.built = a.Target
-               b.addTransitiveLinkDeps(a, a1, "")
+               b.addTransitiveLinkDeps(loaderstate, a, a1, "")
 
                // Sequence the build of the main package (a1) strictly after the build
                // of all other dependencies that go into the link. It is likely to be after
@@ -1034,7 +1035,7 @@ func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action {
 // makes sure those are present in a.Deps.
 // If shlib is non-empty, then a corresponds to the build and installation of shlib,
 // so any rebuild of shlib should not be added as a dependency.
-func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) {
+func (b *Builder) addTransitiveLinkDeps(loaderstate *modload.State, a, a1 *Action, shlib string) {
        // Expand Deps to include all built packages, for the linker.
        // Use breadth-first search to find rebuilt-for-test packages
        // before the standard ones.
@@ -1075,7 +1076,7 @@ func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) {
                        // we'll end up building an overall library or executable that depends at runtime
                        // on other libraries that are out-of-date, which is clearly not good either.
                        // We call it ModeBuggyInstall to make clear that this is not right.
-                       a.Deps = append(a.Deps, b.linkSharedAction(ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil))
+                       a.Deps = append(a.Deps, b.linkSharedAction(loaderstate, ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil))
                }
        }
 }
@@ -1116,21 +1117,21 @@ func (b *Builder) buildmodeShared(mode, depMode BuildMode, args []string, pkgs [
        if err != nil {
                base.Fatalf("%v", err)
        }
-       return b.linkSharedAction(mode, depMode, name, a1)
+       return b.linkSharedAction(modload.LoaderState, mode, depMode, name, a1)
 }
 
 // linkSharedAction takes a grouping action a1 corresponding to a list of built packages
 // and returns an action that links them together into a shared library with the name shlib.
 // If a1 is nil, shlib should be an absolute path to an existing shared library,
 // and then linkSharedAction reads that library to find out the package list.
-func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Action) *Action {
+func (b *Builder) linkSharedAction(loaderstate *modload.State, mode, depMode BuildMode, shlib string, a1 *Action) *Action {
        fullShlib := shlib
        shlib = filepath.Base(shlib)
        a := b.cacheAction("build-shlib "+shlib, nil, func() *Action {
                if a1 == nil {
                        // TODO(rsc): Need to find some other place to store config,
                        // not in pkg directory. See golang.org/issue/22196.
-                       pkgs := readpkglist(fullShlib)
+                       pkgs := readpkglist(loaderstate, fullShlib)
                        a1 = &Action{
                                Mode: "shlib packages",
                        }
@@ -1173,7 +1174,7 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac
                                        }
                                }
                                var stk load.ImportStack
-                               p := load.LoadPackageWithFlags(pkg, base.Cwd(), &stk, nil, 0)
+                               p := load.LoadPackageWithFlags(loaderstate, pkg, base.Cwd(), &stk, nil, 0)
                                if p.Error != nil {
                                        base.Fatalf("load %s: %v", pkg, p.Error)
                                }
@@ -1201,7 +1202,7 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac
                                add(a, dep, true)
                        }
                }
-               b.addTransitiveLinkDeps(a, a1, shlib)
+               b.addTransitiveLinkDeps(loaderstate, a, a1, shlib)
                return a
        })
 
index fdb483d46f21d957ec2239af5007c9c6714d5325..45acbe85c2a6d0d79cea6f6912684996325b937c 100644 (file)
@@ -459,8 +459,8 @@ func oneMainPkg(pkgs []*load.Package) []*load.Package {
 var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
 
 func runBuild(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
-       BuildInit()
+       modload.InitWorkfile(modload.LoaderState)
+       BuildInit(modload.LoaderState)
        b := NewBuilder("")
        defer func() {
                if err := b.Close(); err != nil {
@@ -468,7 +468,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) {
                }
        }()
 
-       pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{AutoVCS: true}, args)
+       pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{AutoVCS: true}, args)
        load.CheckPackageErrors(pkgs)
 
        explicitO := len(cfg.BuildO) > 0
@@ -503,7 +503,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) {
        }
 
        if cfg.BuildCover {
-               load.PrepareForCoverageBuild(pkgs)
+               load.PrepareForCoverageBuild(modload.LoaderState, pkgs)
        }
 
        if cfg.BuildO != "" {
@@ -694,10 +694,10 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) {
                }
        }
 
-       modload.InitWorkfile()
-       BuildInit()
-       pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{AutoVCS: true}, args)
-       if cfg.ModulesEnabled && !modload.HasModRoot() {
+       modload.InitWorkfile(modload.LoaderState)
+       BuildInit(modload.LoaderState)
+       pkgs := load.PackagesAndErrors(modload.LoaderState, ctx, load.PackageOpts{AutoVCS: true}, args)
+       if cfg.ModulesEnabled && !modload.HasModRoot(modload.LoaderState) {
                haveErrors := false
                allMissingErrors := true
                for _, pkg := range pkgs {
@@ -722,7 +722,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) {
        load.CheckPackageErrors(pkgs)
 
        if cfg.BuildCover {
-               load.PrepareForCoverageBuild(pkgs)
+               load.PrepareForCoverageBuild(modload.LoaderState, pkgs)
        }
 
        InstallPackages(ctx, args, pkgs)
@@ -861,9 +861,9 @@ func InstallPackages(ctx context.Context, patterns []string, pkgs []*load.Packag
 func installOutsideModule(ctx context.Context, args []string) {
        modload.LoaderState.ForceUseModules = true
        modload.LoaderState.RootMode = modload.NoRoot
-       modload.AllowMissingModuleImports()
-       modload.Init()
-       BuildInit()
+       modload.AllowMissingModuleImports(modload.LoaderState)
+       modload.Init(modload.LoaderState)
+       BuildInit(modload.LoaderState)
 
        // Load packages. Ignore non-main packages.
        // Print a warning if an argument contains "..." and matches no main packages.
@@ -872,7 +872,7 @@ func installOutsideModule(ctx context.Context, args []string) {
        // TODO(golang.org/issue/40276): don't report errors loading non-main packages
        // matched by a pattern.
        pkgOpts := load.PackageOpts{MainOnly: true}
-       pkgs, err := load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args)
+       pkgs, err := load.PackagesAndErrorsOutsideModule(modload.LoaderState, ctx, pkgOpts, args)
        if err != nil {
                base.Fatal(err)
        }
index 703b4367db31ef18ccdf572447bfbb325ea9524c..eb012d26109f57c12385c421fba6dcb2d99d39b1 100644 (file)
@@ -2193,7 +2193,7 @@ func (noToolchain) cc(b *Builder, a *Action, ofile, cfile string) error {
 // gcc runs the gcc C compiler to create an object from a single C file.
 func (b *Builder) gcc(a *Action, workdir, out string, flags []string, cfile string) error {
        p := a.Package
-       return b.ccompile(a, out, flags, cfile, b.GccCmd(p.Dir, workdir))
+       return b.ccompile(modload.LoaderState, a, out, flags, cfile, b.GccCmd(p.Dir, workdir))
 }
 
 // gas runs the gcc c compiler to create an object file from a single C assembly file.
@@ -2207,23 +2207,23 @@ func (b *Builder) gas(a *Action, workdir, out string, flags []string, sfile stri
                        return fmt.Errorf("package using cgo has Go assembly file %s", sfile)
                }
        }
-       return b.ccompile(a, out, flags, sfile, b.GccCmd(p.Dir, workdir))
+       return b.ccompile(modload.LoaderState, a, out, flags, sfile, b.GccCmd(p.Dir, workdir))
 }
 
 // gxx runs the g++ C++ compiler to create an object from a single C++ file.
 func (b *Builder) gxx(a *Action, workdir, out string, flags []string, cxxfile string) error {
        p := a.Package
-       return b.ccompile(a, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir))
+       return b.ccompile(modload.LoaderState, a, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir))
 }
 
 // gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
 func (b *Builder) gfortran(a *Action, workdir, out string, flags []string, ffile string) error {
        p := a.Package
-       return b.ccompile(a, out, flags, ffile, b.gfortranCmd(p.Dir, workdir))
+       return b.ccompile(modload.LoaderState, a, out, flags, ffile, b.gfortranCmd(p.Dir, workdir))
 }
 
 // ccompile runs the given C or C++ compiler and creates an object from a single source file.
-func (b *Builder) ccompile(a *Action, outfile string, flags []string, file string, compiler []string) error {
+func (b *Builder) ccompile(loaderstate *modload.State, a *Action, outfile string, flags []string, file string, compiler []string) error {
        p := a.Package
        sh := b.Shell(a)
        file = mkAbs(p.Dir, file)
@@ -2260,7 +2260,7 @@ func (b *Builder) ccompile(a *Action, outfile string, flags []string, file strin
                        } else if m.Dir == "" {
                                // The module is in the vendor directory. Replace the entire vendor
                                // directory path, because the module's Dir is not filled in.
-                               from = modload.VendorDir()
+                               from = modload.VendorDir(loaderstate)
                                toPath = "vendor"
                        } else {
                                from = m.Dir
@@ -2310,7 +2310,7 @@ func (b *Builder) ccompile(a *Action, outfile string, flags []string, file strin
                        }
                }
                if len(newFlags) < len(flags) {
-                       return b.ccompile(a, outfile, newFlags, file, compiler)
+                       return b.ccompile(loaderstate, a, outfile, newFlags, file, compiler)
                }
        }
 
@@ -3383,7 +3383,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
        }
        srcs := []string{src}
 
-       p := load.GoFilesPackage(context.TODO(), load.PackageOpts{}, srcs)
+       p := load.GoFilesPackage(modload.LoaderState, context.TODO(), load.PackageOpts{}, srcs)
 
        if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, nil, "", false, "", srcs); e != nil {
                return "32", nil
index e4e83dc8f9853e58fefbdc2b29ff975cf068df5c..a2954ab91ab60aa0567c2e0bc6137b8ae6c045b2 100644 (file)
@@ -50,14 +50,14 @@ func makeCfgChangedEnv() []string {
        return slices.Clip(env)
 }
 
-func BuildInit() {
+func BuildInit(loaderstate *modload.State) {
        if buildInitStarted {
                base.Fatalf("go: internal error: work.BuildInit called more than once")
        }
        buildInitStarted = true
        base.AtExit(closeBuilders)
 
-       modload.Init()
+       modload.Init(loaderstate)
        instrumentInit()
        buildModeInit()
        cfgChangedEnv = makeCfgChangedEnv()
index 18730436ca82176fe260528abb0136c85805fb19..3778e70b687aec30f3bc4f6671c95be06b1622dd 100644 (file)
@@ -143,8 +143,8 @@ func runEditwork(ctx context.Context, cmd *base.Command, args []string) {
        if len(args) == 1 {
                gowork = args[0]
        } else {
-               modload.InitWorkfile()
-               gowork = modload.WorkFilePath()
+               modload.InitWorkfile(modload.LoaderState)
+               gowork = modload.WorkFilePath(modload.LoaderState)
        }
        if gowork == "" {
                base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
index 52185391c115b33c55a618624b021f11b49995fd..20fef91d5e953cdcb4fc652c8b6721728ea06709 100644 (file)
@@ -44,11 +44,11 @@ func init() {
 }
 
 func runInit(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
+       modload.InitWorkfile(modload.LoaderState)
 
        modload.LoaderState.ForceUseModules = true
 
-       gowork := modload.WorkFilePath()
+       gowork := modload.WorkFilePath(modload.LoaderState)
        if gowork == "" {
                gowork = filepath.Join(base.Cwd(), "go.work")
        }
index 640771d8f75996bea08475c1d9306d7222bc38d4..c58cd55ceee39246a4ddd63c050d9efaab86bdf3 100644 (file)
@@ -49,8 +49,8 @@ func init() {
 
 func runSync(ctx context.Context, cmd *base.Command, args []string) {
        modload.LoaderState.ForceUseModules = true
-       modload.InitWorkfile()
-       if modload.WorkFilePath() == "" {
+       modload.InitWorkfile(modload.LoaderState)
+       if modload.WorkFilePath(modload.LoaderState) == "" {
                base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
        }
 
@@ -73,7 +73,7 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
        }
        for _, m := range mms.Versions() {
                opts.MainModule = m
-               _, pkgs := modload.LoadPackages(ctx, opts, "all")
+               _, pkgs := modload.LoadPackages(modload.LoaderState, ctx, opts, "all")
                opts.MainModule = module.Version{} // reset
 
                var (
@@ -91,7 +91,7 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
                mustSelectFor[m] = mustSelect
        }
 
-       workFilePath := modload.WorkFilePath() // save go.work path because EnterModule clobbers it.
+       workFilePath := modload.WorkFilePath(modload.LoaderState) // save go.work path because EnterModule clobbers it.
 
        var goV string
        for _, m := range mms.Versions() {
@@ -114,12 +114,12 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
                // so we don't write some go.mods with the "before" toolchain
                // and others with the "after" toolchain. If nothing else, that
                // discrepancy could show up in auto-recorded toolchain lines.
-               changed, err := modload.EditBuildList(ctx, nil, mustSelectFor[m])
+               changed, err := modload.EditBuildList(modload.LoaderState, ctx, nil, mustSelectFor[m])
                if err != nil {
                        continue
                }
                if changed {
-                       modload.LoadPackages(ctx, modload.PackageOpts{
+                       modload.LoadPackages(modload.LoaderState, ctx, modload.PackageOpts{
                                Tags:                     imports.AnyTags(),
                                Tidy:                     true,
                                VendorModulesInGOROOTSrc: true,
@@ -131,7 +131,7 @@ func runSync(ctx context.Context, cmd *base.Command, args []string) {
                        }, "all")
                        modload.WriteGoMod(ctx, modload.WriteOpts{})
                }
-               goV = gover.Max(goV, modload.LoaderState.MainModules.GoVersion())
+               goV = gover.Max(goV, modload.LoaderState.MainModules.GoVersion(modload.LoaderState))
        }
 
        wf, err := modload.ReadWorkFile(workFilePath)
index 2842163517892ccca1ed5ec19c730cccb5d93474..ca8de22cca884f70c83e981505d54445d726153c 100644 (file)
@@ -62,8 +62,8 @@ func init() {
 
 func runUse(ctx context.Context, cmd *base.Command, args []string) {
        modload.LoaderState.ForceUseModules = true
-       modload.InitWorkfile()
-       gowork := modload.WorkFilePath()
+       modload.InitWorkfile(modload.LoaderState)
+       gowork := modload.WorkFilePath(modload.LoaderState)
        if gowork == "" {
                base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
        }
index f9f0cc0898836fec20a6cf43cefcd215d135a034..36c1f7b522f9e736e57c36411a9309bcd5d2d26a 100644 (file)
@@ -46,8 +46,8 @@ func init() {
 }
 
 func runVendor(ctx context.Context, cmd *base.Command, args []string) {
-       modload.InitWorkfile()
-       if modload.WorkFilePath() == "" {
+       modload.InitWorkfile(modload.LoaderState)
+       if modload.WorkFilePath(modload.LoaderState) == "" {
                base.Fatalf("go: no go.work file found\n\t(run 'go work init' first or specify path using GOWORK environment variable)")
        }