]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modload: cache the Go language version for each module globally
authorBryan C. Mills <bcmills@google.com>
Tue, 21 Jul 2020 20:50:59 +0000 (16:50 -0400)
committerBryan C. Mills <bcmills@google.com>
Mon, 24 Aug 2020 20:44:20 +0000 (20:44 +0000)
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>
src/cmd/go/internal/modload/build.go
src/cmd/go/internal/modload/load.go
src/cmd/go/internal/modload/modfile.go
src/cmd/go/internal/modload/mvs.go

index a101681a1f4f52a38e6a93e891af4e696d7f6f42..b6f955d591ca716a5ee57a9b0f1b78400fed5fc5 100644 (file)
@@ -126,8 +126,8 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList bool) *modi
                Version:  m.Version,
                Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path],
        }
-       if loaded != nil {
-               info.GoVersion = loaded.goVersion[m.Path]
+       if v, ok := rawGoVersion.Load(m); ok {
+               info.GoVersion = v.(string)
        }
 
        // 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
        }
 
        if !fromBuildList {
+               // If this was an explicitly-versioned argument to 'go mod download' or
+               // 'go list -m', report the actual requested version, not its replacement.
                completeFromModCache(info) // Will set m.Error in vendor mode.
                return info
        }
@@ -178,9 +180,12 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList bool) *modi
        // worth the cost, and we're going to overwrite the GoMod and Dir from the
        // replacement anyway. See https://golang.org/issue/27859.
        info.Replace = &modinfo.ModulePublic{
-               Path:      r.Path,
-               Version:   r.Version,
-               GoVersion: info.GoVersion,
+               Path:    r.Path,
+               Version: r.Version,
+       }
+       if goV, ok := rawGoVersion.Load(r); ok {
+               info.Replace.GoVersion = goV.(string)
+               info.GoVersion = info.Replace.GoVersion
        }
        if r.Version == "" {
                if filepath.IsAbs(r.Path) {
index 686d491219d0df3338c69ab6de25e0a16c6253ac..2a37f1d8740c39306ab01c8d60b083a302f8ca90 100644 (file)
@@ -627,8 +627,7 @@ type loader struct {
        pkgCache *par.Cache // map from string to *loadPkg
 
        // computed at end of iterations
-       direct    map[string]bool   // imported directly by main module
-       goVersion map[string]string // go version recorded in each module
+       direct map[string]bool // imported directly by main module
 }
 
 // LoadTests controls whether the loaders load tests of the root packages.
@@ -754,13 +753,6 @@ func (ld *loader) load(roots func() []string) {
                }
        }
 
-       // Add Go versions, computed during walk.
-       ld.goVersion = make(map[string]string)
-       for _, m := range buildList {
-               v, _ := reqs.(*mvsReqs).versions.Load(m)
-               ld.goVersion[m.Path], _ = v.(string)
-       }
-
        // Mix in direct markings (really, lack of indirect markings)
        // from go.mod, unless we scanned the whole module
        // and can therefore be sure we know better than go.mod.
index 9a166cae541c3086e6d0c64cfbbf08b1afb2febb..9ff00e9b5c18a25b21f3ba5b773bef62e810af01 100644 (file)
@@ -7,6 +7,7 @@ package modload
 import (
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
+       "sync"
 
        "golang.org/x/mod/modfile"
        "golang.org/x/mod/module"
@@ -164,3 +165,9 @@ func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool {
 
        return false
 }
+
+// rawGoVersion records the Go version parsed from each module's go.mod file.
+//
+// If a module is replaced, the version of the replacement is keyed by the
+// replacement module.Version, not the version being replaced.
+var rawGoVersion sync.Map // map[module.Version]string
index 39d0d6952410f941e4d75c686c0c6b32033f7338..873f5891c910a302736f0f8957e874cc390e3c6e 100644 (file)
@@ -11,7 +11,6 @@ import (
        "os"
        "path/filepath"
        "sort"
-       "sync"
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
@@ -30,7 +29,6 @@ import (
 type mvsReqs struct {
        buildList []module.Version
        cache     par.Cache
-       versions  sync.Map
 }
 
 // Reqs returns the current module requirement graph.
@@ -83,7 +81,7 @@ func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
 func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
        if mod == Target {
                if modFile != nil && modFile.Go != nil {
-                       r.versions.LoadOrStore(mod, modFile.Go.Version)
+                       rawGoVersion.LoadOrStore(mod, modFile.Go.Version)
                }
                return append([]module.Version(nil), r.buildList[1:]...), nil
        }
@@ -113,7 +111,7 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
                                return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
                        }
                        if f.Go != nil {
-                               r.versions.LoadOrStore(mod, f.Go.Version)
+                               rawGoVersion.LoadOrStore(repl, f.Go.Version)
                        }
                        return r.modFileToList(f), nil
                }
@@ -147,7 +145,7 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
                but was required as: %s`, mpath, origPath))
        }
        if f.Go != nil {
-               r.versions.LoadOrStore(mod, f.Go.Version)
+               rawGoVersion.LoadOrStore(mod, f.Go.Version)
        }
 
        return r.modFileToList(f), nil