Skip to content

Commit 2a9636d

Browse files
author
Bryan C. Mills
committed
cmd/go/internal/modload: cache the Go language version for each module globally
Previously, this cache was a member of the (ephemeral) modload.loader struct. However, the Go language version for a given module version does not vary based on the build list, the set of loaded packages, the build tags in use, the meaning of the "all" pattern, or anything else that can be configured for an instance of the package loader. The map containing that information is therefore not appropriate as a field of the (configurable, package-list-dependent) loader struct. The Go language version mapping could, in theory, be read from the go.mod file in the module cache (or replacement directory) every time it is needed: this map is just a cache, and as such it belongs alongside the other caches and indexes in the modload package, which are currently found in modfile.go. We may want to do the same sort of global caching for the mapping from each module.Version to its list of direct requirements (which are similarly idempotent), but for now that is left for a future change. For #36460 For #36876 Change-Id: I90ac176ffea97f30c47d6540c3dfb874dc9cfa4f Reviewed-on: https://go-review.googlesource.com/c/go/+/244078 Reviewed-by: Jay Conrod <jayconrod@google.com> Reviewed-by: Michael Matloob <matloob@golang.org>
1 parent c777863 commit 2a9636d

File tree

4 files changed

+21
-19
lines changed

4 files changed

+21
-19
lines changed

src/cmd/go/internal/modload/build.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList bool) *modi
126126
Version: m.Version,
127127
Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path],
128128
}
129-
if loaded != nil {
130-
info.GoVersion = loaded.goVersion[m.Path]
129+
if v, ok := rawGoVersion.Load(m); ok {
130+
info.GoVersion = v.(string)
131131
}
132132

133133
// completeFromModCache fills in the extra fields in m using the module cache.
@@ -155,6 +155,8 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList bool) *modi
155155
}
156156

157157
if !fromBuildList {
158+
// If this was an explicitly-versioned argument to 'go mod download' or
159+
// 'go list -m', report the actual requested version, not its replacement.
158160
completeFromModCache(info) // Will set m.Error in vendor mode.
159161
return info
160162
}
@@ -178,9 +180,12 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList bool) *modi
178180
// worth the cost, and we're going to overwrite the GoMod and Dir from the
179181
// replacement anyway. See https://golang.org/issue/27859.
180182
info.Replace = &modinfo.ModulePublic{
181-
Path: r.Path,
182-
Version: r.Version,
183-
GoVersion: info.GoVersion,
183+
Path: r.Path,
184+
Version: r.Version,
185+
}
186+
if goV, ok := rawGoVersion.Load(r); ok {
187+
info.Replace.GoVersion = goV.(string)
188+
info.GoVersion = info.Replace.GoVersion
184189
}
185190
if r.Version == "" {
186191
if filepath.IsAbs(r.Path) {

src/cmd/go/internal/modload/load.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -627,8 +627,7 @@ type loader struct {
627627
pkgCache *par.Cache // map from string to *loadPkg
628628

629629
// computed at end of iterations
630-
direct map[string]bool // imported directly by main module
631-
goVersion map[string]string // go version recorded in each module
630+
direct map[string]bool // imported directly by main module
632631
}
633632

634633
// LoadTests controls whether the loaders load tests of the root packages.
@@ -754,13 +753,6 @@ func (ld *loader) load(roots func() []string) {
754753
}
755754
}
756755

757-
// Add Go versions, computed during walk.
758-
ld.goVersion = make(map[string]string)
759-
for _, m := range buildList {
760-
v, _ := reqs.(*mvsReqs).versions.Load(m)
761-
ld.goVersion[m.Path], _ = v.(string)
762-
}
763-
764756
// Mix in direct markings (really, lack of indirect markings)
765757
// from go.mod, unless we scanned the whole module
766758
// and can therefore be sure we know better than go.mod.

src/cmd/go/internal/modload/modfile.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package modload
77
import (
88
"cmd/go/internal/base"
99
"cmd/go/internal/cfg"
10+
"sync"
1011

1112
"golang.org/x/mod/modfile"
1213
"golang.org/x/mod/module"
@@ -164,3 +165,9 @@ func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool {
164165

165166
return false
166167
}
168+
169+
// rawGoVersion records the Go version parsed from each module's go.mod file.
170+
//
171+
// If a module is replaced, the version of the replacement is keyed by the
172+
// replacement module.Version, not the version being replaced.
173+
var rawGoVersion sync.Map // map[module.Version]string

src/cmd/go/internal/modload/mvs.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"os"
1212
"path/filepath"
1313
"sort"
14-
"sync"
1514

1615
"cmd/go/internal/base"
1716
"cmd/go/internal/cfg"
@@ -30,7 +29,6 @@ import (
3029
type mvsReqs struct {
3130
buildList []module.Version
3231
cache par.Cache
33-
versions sync.Map
3432
}
3533

3634
// Reqs returns the current module requirement graph.
@@ -83,7 +81,7 @@ func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
8381
func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
8482
if mod == Target {
8583
if modFile != nil && modFile.Go != nil {
86-
r.versions.LoadOrStore(mod, modFile.Go.Version)
84+
rawGoVersion.LoadOrStore(mod, modFile.Go.Version)
8785
}
8886
return append([]module.Version(nil), r.buildList[1:]...), nil
8987
}
@@ -113,7 +111,7 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
113111
return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
114112
}
115113
if f.Go != nil {
116-
r.versions.LoadOrStore(mod, f.Go.Version)
114+
rawGoVersion.LoadOrStore(repl, f.Go.Version)
117115
}
118116
return r.modFileToList(f), nil
119117
}
@@ -147,7 +145,7 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
147145
but was required as: %s`, mpath, origPath))
148146
}
149147
if f.Go != nil {
150-
r.versions.LoadOrStore(mod, f.Go.Version)
148+
rawGoVersion.LoadOrStore(mod, f.Go.Version)
151149
}
152150

153151
return r.modFileToList(f), nil

0 commit comments

Comments
 (0)