cmd/go: refactor usage of requirements

This commit refactors usage of the global variable `requirements` to
the global LoaderState field of the same name.

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

[git-generate]
cd src/cmd/go/internal/modload
rf 'ex { requirements -> LoaderState.requirements }'
rf 'add State.MainModules \
// requirements is the requirement graph for the main module.\
//\
// It is always non-nil if the main module'\\\''s go.mod file has been\
// loaded.\
//\
// This variable should only be read from the loadModFile\
// function, and should only be written in the loadModFile and\
// commitRequirements functions.  All other functions that need or\
// produce a *Requirements should accept and/or return an explicit\
// parameter.'
rf 'rm requirements'

Change-Id: I9d7d1d301a9e89f9214ce632fa5b656dd2940f39
Reviewed-on: https://go-review.googlesource.com/c/go/+/698061
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
Reviewed-by: Michael Matloob <matloob@google.com>
This commit is contained in:
Ian Alexander 2025-08-20 20:14:59 -04:00
parent a1661e776f
commit 1623927730
4 changed files with 40 additions and 39 deletions

View file

@ -85,16 +85,6 @@ type cachedGraph struct {
err error // If err is non-nil, mg may be incomplete (but must still be non-nil). err error // If err is non-nil, mg may be incomplete (but must still be non-nil).
} }
// requirements is the requirement graph for the main module.
//
// It is always non-nil if the main module's go.mod file has been loaded.
//
// This variable should only be read from the loadModFile function, and should
// only be written in the loadModFile and commitRequirements functions.
// All other functions that need or produce a *Requirements should
// accept and/or return an explicit parameter.
var requirements *Requirements
func mustHaveGoRoot(roots []module.Version) { func mustHaveGoRoot(roots []module.Version) {
for _, m := range roots { for _, m := range roots {
if m.Path == "go" { if m.Path == "go" {
@ -589,7 +579,7 @@ func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
requirements = rs LoaderState.requirements = rs
return mg, nil return mg, nil
} }
@ -654,7 +644,7 @@ func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (chang
if err != nil { if err != nil {
return false, err return false, err
} }
requirements = rs LoaderState.requirements = rs
return changed, nil return changed, nil
} }

View file

@ -59,7 +59,7 @@ var (
// EnterModule resets MainModules and requirements to refer to just this one module. // EnterModule resets MainModules and requirements to refer to just this one module.
func EnterModule(ctx context.Context, enterModroot string) { func EnterModule(ctx context.Context, enterModroot string) {
LoaderState.MainModules = nil // reset MainModules LoaderState.MainModules = nil // reset MainModules
requirements = nil LoaderState.requirements = nil
workFilePath = "" // Force module mode workFilePath = "" // Force module mode
modfetch.Reset() modfetch.Reset()
@ -90,7 +90,7 @@ func EnterWorkspace(ctx context.Context) (exit func(), err error) {
// Update the content of the previous main module, and recompute the requirements. // Update the content of the previous main module, and recompute the requirements.
*LoaderState.MainModules.ModFile(mm) = *updatedmodfile *LoaderState.MainModules.ModFile(mm) = *updatedmodfile
requirements = requirementsFromModFiles(ctx, LoaderState.MainModules.workFile, slices.Collect(maps.Values(LoaderState.MainModules.modFiles)), nil) LoaderState.requirements = requirementsFromModFiles(ctx, LoaderState.MainModules.workFile, slices.Collect(maps.Values(LoaderState.MainModules.modFiles)), nil)
return func() { return func() {
setState(oldstate) setState(oldstate)
@ -395,7 +395,7 @@ func setState(s State) State {
modRoots: LoaderState.modRoots, modRoots: LoaderState.modRoots,
modulesEnabled: cfg.ModulesEnabled, modulesEnabled: cfg.ModulesEnabled,
MainModules: LoaderState.MainModules, MainModules: LoaderState.MainModules,
requirements: requirements, requirements: LoaderState.requirements,
} }
LoaderState.initialized = s.initialized LoaderState.initialized = s.initialized
LoaderState.ForceUseModules = s.ForceUseModules LoaderState.ForceUseModules = s.ForceUseModules
@ -403,7 +403,7 @@ func setState(s State) State {
LoaderState.modRoots = s.modRoots LoaderState.modRoots = s.modRoots
cfg.ModulesEnabled = s.modulesEnabled cfg.ModulesEnabled = s.modulesEnabled
LoaderState.MainModules = s.MainModules LoaderState.MainModules = s.MainModules
requirements = s.requirements LoaderState.requirements = s.requirements
workFilePath = s.workFilePath workFilePath = s.workFilePath
// The modfetch package's global state is used to compute // The modfetch package's global state is used to compute
// the go.sum file, so save and restore it along with the // the go.sum file, so save and restore it along with the
@ -430,6 +430,17 @@ type State struct {
modRoots []string modRoots []string
modulesEnabled bool modulesEnabled bool
MainModules *MainModuleSet MainModules *MainModuleSet
// requirements is the requirement graph for the main module.
//
// It is always non-nil if the main module's go.mod file has been
// loaded.
//
// This variable should only be read from the loadModFile
// function, and should only be written in the loadModFile and
// commitRequirements functions. All other functions that need or
// produce a *Requirements should accept and/or return an explicit
// parameter.
requirements *Requirements requirements *Requirements
workFilePath string workFilePath string
modfetchState modfetch.State modfetchState modfetch.State
@ -869,8 +880,8 @@ func LoadModFile(ctx context.Context) *Requirements {
} }
func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) { func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) {
if requirements != nil { if LoaderState.requirements != nil {
return requirements, nil return LoaderState.requirements, nil
} }
Init() Init()
@ -939,14 +950,14 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
} }
} }
rawGoVersion.Store(mainModule, goVersion) rawGoVersion.Store(mainModule, goVersion)
requirements = newRequirements(pruning, roots, direct) LoaderState.requirements = newRequirements(pruning, roots, direct)
if cfg.BuildMod == "vendor" { if cfg.BuildMod == "vendor" {
// For issue 56536: Some users may have GOFLAGS=-mod=vendor set. // For issue 56536: Some users may have GOFLAGS=-mod=vendor set.
// Make sure it behaves as though the fake module is vendored // Make sure it behaves as though the fake module is vendored
// with no dependencies. // with no dependencies.
requirements.initVendor(nil) LoaderState.requirements.initVendor(nil)
} }
return requirements, nil return LoaderState.requirements, nil
} }
var modFiles []*modfile.File var modFiles []*modfile.File
@ -1035,7 +1046,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
if inWorkspaceMode() { if inWorkspaceMode() {
// We don't need to update the mod file so return early. // We don't need to update the mod file so return early.
requirements = rs LoaderState.requirements = rs
return rs, nil return rs, nil
} }
@ -1081,8 +1092,8 @@ func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error)
} }
} }
requirements = rs LoaderState.requirements = rs
return requirements, nil return LoaderState.requirements, nil
} }
func errWorkTooOld(gomod string, wf *modfile.WorkFile, goVers string) error { func errWorkTooOld(gomod string, wf *modfile.WorkFile, goVers string) error {
@ -1162,7 +1173,7 @@ func CreateModFile(ctx context.Context, modPath string) {
if err != nil { if err != nil {
base.Fatal(err) base.Fatal(err)
} }
requirements = rs LoaderState.requirements = rs
if err := commitRequirements(ctx, WriteOpts{}); err != nil { if err := commitRequirements(ctx, WriteOpts{}); err != nil {
base.Fatal(err) base.Fatal(err)
} }
@ -1801,7 +1812,7 @@ type WriteOpts struct {
// WriteGoMod writes the current build list back to go.mod. // WriteGoMod writes the current build list back to go.mod.
func WriteGoMod(ctx context.Context, opts WriteOpts) error { func WriteGoMod(ctx context.Context, opts WriteOpts) error {
requirements = LoadModFile(ctx) LoaderState.requirements = LoadModFile(ctx)
return commitRequirements(ctx, opts) return commitRequirements(ctx, opts)
} }
@ -1828,7 +1839,7 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b
var list []*modfile.Require var list []*modfile.Require
toolchain := "" toolchain := ""
goVersion := "" goVersion := ""
for _, m := range requirements.rootModules { for _, m := range LoaderState.requirements.rootModules {
if m.Path == "go" { if m.Path == "go" {
goVersion = m.Version goVersion = m.Version
continue continue
@ -1839,7 +1850,7 @@ func UpdateGoModFromReqs(ctx context.Context, opts WriteOpts) (before, after []b
} }
list = append(list, &modfile.Require{ list = append(list, &modfile.Require{
Mod: m, Mod: m,
Indirect: !requirements.direct[m.Path], Indirect: !LoaderState.requirements.direct[m.Path],
}) })
} }
@ -1913,7 +1924,7 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) {
if inWorkspaceMode() { if inWorkspaceMode() {
// go.mod files aren't updated in workspace mode, but we still want to // go.mod files aren't updated in workspace mode, but we still want to
// update the go.work.sum file. // update the go.work.sum file.
return modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()) return modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements())
} }
_, updatedGoMod, modFile, err := UpdateGoModFromReqs(ctx, opts) _, updatedGoMod, modFile, err := UpdateGoModFromReqs(ctx, opts)
if err != nil { if err != nil {
@ -1937,7 +1948,7 @@ 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. // 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. // 'go mod init' shouldn't write go.sum, since it will be incomplete.
if cfg.CmdName != "mod init" { if cfg.CmdName != "mod init" {
if err := modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil { if err := modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements()); err != nil {
return err return err
} }
} }
@ -1960,7 +1971,7 @@ func commitRequirements(ctx context.Context, opts WriteOpts) (err error) {
// 'go mod init' shouldn't write go.sum, since it will be incomplete. // 'go mod init' shouldn't write go.sum, since it will be incomplete.
if cfg.CmdName != "mod init" { if cfg.CmdName != "mod init" {
if err == nil { if err == nil {
err = modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, requirements, addBuildListZipSums), mustHaveCompleteRequirements()) err = modfetch.WriteGoSum(ctx, keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums), mustHaveCompleteRequirements())
} }
} }
}() }()

View file

@ -109,7 +109,7 @@ func ListModules(ctx context.Context, args []string, mode ListMode, reuseFile st
} }
if err == nil { if err == nil {
requirements = rs LoaderState.requirements = rs
// TODO(#61605): The extra ListU clause fixes a problem with Go 1.21rc3 // TODO(#61605): The extra ListU clause fixes a problem with Go 1.21rc3
// where "go mod tidy" and "go list -m -u all" fight over whether the go.sum // where "go mod tidy" and "go list -m -u all" fight over whether the go.sum
// should be considered up-to-date. The fix for now is to always treat the // should be considered up-to-date. The fix for now is to always treat the

View file

@ -455,7 +455,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
if opts.TidyDiff { if opts.TidyDiff {
cfg.BuildMod = "readonly" cfg.BuildMod = "readonly"
loaded = ld loaded = ld
requirements = loaded.requirements LoaderState.requirements = loaded.requirements
currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(ctx, WriteOpts{}) currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(ctx, WriteOpts{})
if err != nil { if err != nil {
base.Fatal(err) 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. // Dropping compatibility for 1.16 may result in a strictly smaller go.sum.
// Update the keep map with only the loaded.requirements. // Update the keep map with only the loaded.requirements.
if gover.Compare(compatVersion, "1.16") > 0 { if gover.Compare(compatVersion, "1.16") > 0 {
keep = keepSums(ctx, loaded, requirements, addBuildListZipSums) keep = keepSums(ctx, loaded, LoaderState.requirements, addBuildListZipSums)
} }
currentGoSum, tidyGoSum := modfetch.TidyGoSum(keep) currentGoSum, tidyGoSum := modfetch.TidyGoSum(keep)
goSumDiff := diff.Diff("current/go.sum", currentGoSum, "tidy/go.sum", tidyGoSum) goSumDiff := diff.Diff("current/go.sum", currentGoSum, "tidy/go.sum", tidyGoSum)
@ -505,7 +505,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
// to call WriteGoMod itself) or if ResolveMissingImports is false (the // to call WriteGoMod itself) or if ResolveMissingImports is false (the
// command wants to examine the package graph as-is). // command wants to examine the package graph as-is).
loaded = ld loaded = ld
requirements = loaded.requirements LoaderState.requirements = loaded.requirements
for _, pkg := range ld.pkgs { for _, pkg := range ld.pkgs {
if !pkg.isTest() { if !pkg.isTest() {
@ -788,7 +788,7 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
return roots return roots
}, },
}) })
requirements = loaded.requirements LoaderState.requirements = loaded.requirements
if !ExplicitWriteGoMod { if !ExplicitWriteGoMod {
if err := commitRequirements(ctx, WriteOpts{}); err != nil { if err := commitRequirements(ctx, WriteOpts{}); err != nil {