Skip to content

cmd/go: no 'go get' command promotes an implicit dependency to an explicit one #43131

@bcmills

Description

@bcmills

While testing some other behaviors for #36460, I noticed a curious interaction between go get and -mod=readonly.

If a package or test in the main module directly imports a package found in an implicit (transitive) dependency, go build and go test invocations for that package with -mod=readonly will fail with updates to go.mod needed, because the go command has always maintained the invariant that modules directly imported by the main module are explicit requirements.

In this situation, the go command recommends running go mod tidy, which is usually the first tool users ought to consider for dependency problems. However, a user who does not want to lose other temporary edits to the go.mod file might prefer to instead use go get to promote only one specific package instead.

Unfortunately, if the module containing the package passed to go get is already transitively required at the requested version, go get does not promote that module from an implicit dependency to an explicit one. (It will under lazy loading, but does not yet.)

The user can work around this problem by running go mod edit -require to add the requirement explicitly, but we would rather not encourage users to reach for go mod edit to make dependency changes, as it does not ensure that the resulting requirements are consistent.

Now that -mod=readonly is the default (#40728), I think users will be much more likely to encounter this awkward interaction. They may be frustrated by it, and might not consider the go mod edit workaround.

For Go 1.16, perhaps we should make go get -d always record explicit dependencies for the requested packages, which can be subsequently cleaned up with an explicit go mod tidy.

$ go version
go version devel +6c64b6db6 Thu Dec 10 03:18:00 2020 +0000 linux/amd64

$ go list all
usemod/usemod.go:3:8: no required module provides package golang.org/x/mod/module; try 'go mod tidy' to add it
usetools/usetools.go:3:8: no required module provides package golang.org/x/tools/go/packages; try 'go mod tidy' to add it

$ go get -d golang.org/x/tools/go/packages
go: downloading golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11
go: downloading golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
go: downloading golang.org/x/mod v0.3.0
go get: added golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11

$ go list -deps ./usetools >/dev/null

$ go list -deps ./usemod >/dev/null
go: updates to go.mod needed; try 'go mod tidy' first

$ cat go.mod
module example.com

go 1.16

require golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11 // indirect

$ go list -m all
example.com
github.com/yuin/goldmark v1.2.1
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/mod v0.3.0
golang.org/x/net v0.0.0-20201021035429-f5854403a974
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
golang.org/x/text v0.3.3
golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1

$ go get -d golang.org/x/mod@v0.3.0

$ cat go.mod
module example.com

go 1.16

require golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11 // indirect

$ go list -deps ./usemod >/dev/null
go: updates to go.mod needed; try 'go mod tidy' first

$ go mod edit -require=golang.org/x/mod@v0.3.0

$ cat go.mod
module example.com

go 1.16

require (
        golang.org/x/mod v0.3.0
        golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11 // indirect
)

$ go list -deps ./usemod >/dev/null

$

-- go.mod --
module example.com

go 1.16
-- usemod/usemod.go --
package usemod

import _ "golang.org/x/mod/module"
-- usetools/usetools.go --
package usetools

import _ "golang.org/x/tools/go/packages"

CC @jayconrod @matloob

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.modulesrelease-blocker

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions