Skip to content

Commit 0e09e41

Browse files
author
Bryan C. Mills
committed
cmd/go: assume Go 1.16 semantics uniformly for unversioned modules
However, still only trigger -mod=vendor automatically (and only apply the more stringent Go 1.14 vendor consistency checks) if the 'go' version is explicit. This provides maximal compatibility with Go 1.16 and earlier: Go 1.11 modules will continue not to fail vendor consistency checks, but scripts that assume semantics up to Go 1.16 for unversioned modules will continue to work unmodified. Fixes #44976 For #36460 Change-Id: Idb05ca320023f57249c71fc8079218e8991d1ff9 Reviewed-on: https://go-review.googlesource.com/c/go/+/308509 Trust: Bryan C. Mills <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 31d2556 commit 0e09e41

File tree

4 files changed

+45
-55
lines changed

4 files changed

+45
-55
lines changed

src/cmd/go/internal/modload/init.go

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -431,30 +431,22 @@ func LoadModFile(ctx context.Context) *Requirements {
431431
// automatically since Go 1.12, so this module either dates to Go 1.11 or
432432
// has been erroneously hand-edited.
433433
//
434+
// The semantics of the go.mod file are more-or-less the same from Go 1.11
435+
// through Go 1.16, changing at 1.17 for lazy loading. So even though a
436+
// go.mod file without a 'go' directive is theoretically a Go 1.11 file,
437+
// scripts may assume that it ends up as a Go 1.16 module. We can't go
438+
// higher than that, because we don't know which semantics the user intends.
439+
//
440+
// (Note that 'go mod init' always adds the latest version, so scripts that
441+
// use 'go mod init' will result in current-version modules instead of Go
442+
// 1.16 modules.)
443+
//
434444
// If we are able to modify the go.mod file, we will add a 'go' directive
435445
// to at least make the situation explicit going forward.
436446
if cfg.BuildMod == "mod" {
437-
// TODO(#44976): If we implicitly upgrade to the latest Go version once
438-
// lazy loading is implemented, we could accidentally prune out
439-
// dependencies from what was formerly a Go 1.11 module, resulting in
440-
// downgrades (if only lower requirements on that module remain) and/or
441-
// upgrades (if no requirement remains and we end up re-resolving to
442-
// latest).
443-
//
444-
// We should probably instead load the dependencies using Go 1.11
445-
// semantics to ensure that we capture everything that is relevant, or
446-
// perhaps error out and let the user tell us which version they intend.
447-
//
448-
// If we are running 'go mod tidy' in particular, we will have enough
449-
// information to upgrade the 'go' version after loading is complete.
450-
addGoStmt(latestGoVersion())
447+
addGoStmt("1.16")
451448
} else {
452-
// Reproducibility requires that if we change the semantics of a module,
453-
// we write some explicit change to its go.mod file. We cannot write to
454-
// the go.mod file (because we are in readonly or vendor mode), so we must
455-
// not change its semantics either. The go.mod file looks as if it were
456-
// created by Go 1.11, so assume Go 1.11 semantics.
457-
rawGoVersion.Store(Target, "1.11")
449+
rawGoVersion.Store(Target, "1.16")
458450
}
459451
}
460452

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd
291291
// (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages
292292
// transitively *imported by* the packages and tests in the main module.)
293293
func (i *modFileIndex) allPatternClosesOverTests() bool {
294-
if i != nil && semver.Compare(i.goVersionV, narrowAllVersionV) < 0 {
294+
if i != nil && i.goVersionV != "" && semver.Compare(i.goVersionV, narrowAllVersionV) < 0 {
295295
// The module explicitly predates the change in "all" for lazy loading, so
296296
// continue to use the older interpretation. (If i == nil, we not in any
297297
// module at all and should use the latest semantics.)

src/cmd/go/testdata/script/mod_go_version_missing.txt

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,48 @@
11
cp go.mod go.mod.orig
22

3-
# With -mod=readonly, we should not update the go version in use.
4-
#
5-
# We started adding the go version automatically in Go 1.12, so a module without
6-
# one encountered in the wild (such as in the module cache) should assume Go
7-
# 1.11 semantics.
3+
# For modules whose go.mod file does not include a 'go' directive,
4+
# we assume the language and dependency semantics of Go 1.16,
5+
# but do not trigger “automatic vendoring” mode (-mod=vendor),
6+
# which was added in Go 1.14 and was not triggered
7+
# under the same conditions in Go 1.16 (which would instead
8+
# default to -mod=readonly when no 'go' directive is present).
89

9-
# For Go 1.11 modules, 'all' should include dependencies of tests.
10-
# (They are pruned out as of Go 1.16.)
10+
# For Go 1.16 modules, 'all' should prune out dependencies of tests,
11+
# even if the 'go' directive is missing.
1112

1213
go list -mod=readonly all
1314
stdout '^example.com/dep$'
14-
stdout '^example.com/testdep$'
15+
! stdout '^example.com/testdep$'
1516
cp stdout list-1.txt
1617
cmp go.mod go.mod.orig
1718

18-
# For Go 1.11 modules, automatic vendoring should not take effect.
19-
# (That behavior was added in Go 1.14.)
19+
# We should only default to -mod=vendor if the 'go' directive is explicit in the
20+
# go.mod file. Otherwise, we don't actually know whether the module was written
21+
# against Go 1.11 or 1.16. We would have to update the go.mod file to clarify,
22+
# and as of Go 1.16 we don't update the go.mod file by default.
23+
#
24+
# If we set -mod=vendor explicitly, we shouldn't apply the Go 1.14
25+
# consistency check, because — again — we don't know whether we're in a 1.11
26+
# module or a bad-script-edited 1.16 module.
2027

21-
go list all # should default to -mod=readonly, not -mod=vendor.
22-
cmp stdout list-1.txt
28+
! go list -mod=vendor all
29+
! stderr '^go: inconsistent vendoring'
30+
stderr 'cannot find package "\." in:\n\t.*[/\\]vendor[/\\]example.com[/\\]badedit$'
2331

2432
# When we set -mod=mod, the go version should be updated immediately,
25-
# narrowing the "all" pattern reported by that command.
33+
# to Go 1.16 (not the current version).
2634

2735
go list -mod=mod all
2836
! stdout '^example.com/testdep$'
29-
cp stdout list-2.txt
30-
cmpenv go.mod go.mod.want
31-
32-
go list -mod=mod all
33-
cmp stdout list-2.txt
37+
cmp stdout list-1.txt
38+
cmp go.mod go.mod.want
3439

35-
# The updated version should have been written back to go.mod, so
36-
# automatic vendoring should come into effect (and fail).
40+
# The updated version should have been written back to go.mod, so now the 'go'
41+
# directive is explicit. -mod=vendor should trigger by default, and the stronger
42+
# Go 1.14 consistency check should apply.
3743
! go list all
3844
stderr '^go: inconsistent vendoring'
39-
40-
cp go.mod.orig go.mod
41-
42-
# In readonly or vendor mode (not -mod=mod), the inferred Go version is 1.11.
43-
# For Go 1.11 modules, Go 1.13 features should not be enabled.
44-
45-
! go build -mod=readonly .
46-
stderr '^# example\.com/m\n\.[/\\]m\.go:5:11: underscores in numeric literals requires go1\.13 or later \(-lang was set to go1\.11; check go\.mod\)$'
47-
cmp go.mod go.mod.orig
45+
! stderr badedit
4846

4947

5048
-- go.mod --
@@ -59,7 +57,7 @@ replace (
5957
-- go.mod.want --
6058
module example.com/m
6159

62-
go $goversion
60+
go 1.16
6361

6462
require example.com/dep v0.1.0
6563

@@ -69,7 +67,7 @@ replace (
6967
)
7068
-- vendor/example.com/dep/dep.go --
7169
package dep
72-
import _ "example.com/bananas"
70+
import _ "example.com/badedit"
7371
-- vendor/modules.txt --
7472
HAHAHA this is broken.
7573

src/cmd/go/testdata/script/mod_retention.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ cmp go.mod go.mod.tidy
6464
# However, that should not remove other redundant requirements.
6565
cp go.mod.nogo go.mod
6666
go list -mod=mod all
67-
cmpenv go.mod go.mod.currentgo
67+
cmpenv go.mod go.mod.addedgo
6868

6969

7070
-- go.mod.tidy --
@@ -133,10 +133,10 @@ require (
133133
rsc.io/sampler v1.3.0 // indirect
134134
rsc.io/testonly v1.0.0 // indirect
135135
)
136-
-- go.mod.currentgo --
136+
-- go.mod.addedgo --
137137
module m
138138

139-
go $goversion
139+
go 1.16
140140

141141
require (
142142
rsc.io/quote v1.5.2

0 commit comments

Comments
 (0)