Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
bcmills opened this issue Dec 11, 2020 · 5 comments
Closed
Labels
FrozenDueToAge modules NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. release-blocker
Milestone

Comments

@bcmills
Copy link
Contributor

bcmills commented Dec 11, 2020

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

@bcmills bcmills added NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. release-blocker okay-after-beta1 Used by release team to mark a release-blocker issue as okay to resolve either before or after beta1 labels Dec 11, 2020
@bcmills bcmills added this to the Go1.16 milestone Dec 11, 2020
@bcmills
Copy link
Contributor Author

bcmills commented Dec 11, 2020

I think @heschik was asking about this a couple weeks ago, in the context of gopls rather than -mod=readonly.

@heschi
Copy link
Contributor

heschi commented Dec 11, 2020

Yeah, I just used go mod edit to add a direct require first.

@gopherbot
Copy link

Change https://golang.org/cl/277355 mentions this issue: cmd/go: print hint when 'go install' run without version outside module

@gopherbot
Copy link

Change https://golang.org/cl/278812 mentions this issue: cmd/go: in 'go get', promote named implicit dependencies to explicit

@toothrot toothrot removed the okay-after-beta1 Used by release team to mark a release-blocker issue as okay to resolve either before or after beta1 label Dec 17, 2020
@gopherbot
Copy link

Change https://golang.org/cl/279528 mentions this issue: cmd/go/internal/modload: add hint for missing implicit dependency

gopherbot pushed a commit that referenced this issue Dec 22, 2020
By default (and with -mod=readonly), the go command imports an error
if a package provided by an implicitly required module is
imported by a package in the main module. This import requires an
update to go.mod: the module must be required explicitly.

The package loader now provides a hint that 'go get' should be run on
the importing package. This is preferred to 'go get' on the imported
package, since that would add an "// indirect" requirement.

For #43131

Change-Id: I0b353ce8ac8c4ddf1a9863544dfaf6c1964daf42
Reviewed-on: https://go-review.googlesource.com/c/go/+/279528
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
@golang golang locked and limited conversation to collaborators Dec 23, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge modules NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. release-blocker
Projects
None yet
Development

No branches or pull requests

4 participants