-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: ensure that 'go mod tidy' and go get -u
do not introduce ambiguous imports
#27899
Comments
If two modules don't have actual dependency but |
@hyangah, I'm not sure what you mean? If you're changing module boundaries, there should always be a cycle. (Reason # 1 imposes a requirement edge in one direction, while # 2 imposes the other direction: I can't think of a situation where we would need to preserve the edge but not have a cycle.) |
@bcmills my comment is about how to change |
Sorry if this is just noise, and I wouldn't suggest this as a long term solution, but adding a comment here in case it triggers some discussion and/or a better idea. To avoid I have not tested this on an actual repo, but if you wanted to take a module In the root of the repo:
In theory, a later This technique would be somewhat analogous to the (Side note: example above creates |
@thepudds, that's a nice workaround, but it's slightly fragile: if the package that we put in the |
@bcmills, agreed -- it would take some care to set up initially, and then take some care to not mess up later if there are additional moves. Hopefully the core go tooling has some additional logic targeting these types of scenarios in 1.12 or so such that something like this is no longer needed. That said, I was trying to think if there was something that could work in 1.11 (aside from "never run |
I don't think we can a priori assume that every cycle should be kept. |
In https://golang.org/issue/27858#issuecomment-434713751, @jba suggests:
That would allow for a single |
(CC @jayconrod) @jba's suggestion solves the “missing package when moving out” direction (1), but not the “ambiguous import when moving in” direction (2). But perhaps we could resolve that similarly: if we detect an ambiguous import, before we emit an error we could try to upgrade away all of the otherwise-unconstrained modules providing that package. For example, if we execute
and we detect that, as a result, package
|
(Note that an N-way collision is possible if N different modules are passed to |
To summarize, the options so far are:
|
It seems like the issue is that we have version requirements that don't match import requirements, and There are other cases like this, too, right? From #25922, we need this for tool dependencies. Also, a more mundane examples: "I call a function in module A that returns a struct type defined in module B. I don't import packages from B directly, but I need a field added in B v1.2, and A only depends on v1.1". I don't think I like @hyangah's suggestion of having a |
That case is a bit different: import collisions are, at least in principle, easy to detect, whereas tool dependencies are not.
In that case, |
go get -u
do not introduce ambiguous imports
…#2057) Updates #2048 - moves the go.mod file from samples/appengine to samples. Note the replace gocloud.dev => ../ added to the go.mod. Without this, running go test ./... in samples/ results in many errors like: can't load package: package gocloud.dev/samples/server: unknown import path "gocloud.dev/samples/server": ambiguous import: found gocloud.dev/samples/server in multiple modules: gocloud.dev/samples (/home/eliben/eli/go-cloud/samples/server) gocloud.dev v0.13.0 (/home/eliben/eli/go/pkg/mod/gocloud.dev@v0.13.0/samples/server) The symptom and solution is explained by bcmills in ugorji/go#279 (which refers also to golang/go#27899). The new go.mod points to gocloud.dev v0.13, which also provides these packages - so the go command is confused - it sees the same package(s) provided by two different modules. The ugorji/go solution was to use a pseudo-version pointing at an existing commit in the core module which removes the packages - this removes the ambiguity. In our case, there is no existing commit yet - so I'm using a replace line. The replace line should be unnecessary when we release a new CDK version. This has interesting implications for #886 - we'll likely have to do the same when we split out providers to their own modules and retain replace lines until a new release.
Change https://golang.org/cl/196298 mentions this issue: |
This consolidates the construction of 'ambiguous import' errors to a single location, ensuring consistency, and lays the groundwork for automatic resolution in the future. While we're at it, change "found" to "found package" to try to make the cause of the error clearer. Updates #32128 Updates #27899 Change-Id: I14a93593320e5c60d20b0eb686d0d5355763c30c Reviewed-on: https://go-review.googlesource.com/c/go/+/196298 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
This approach works for upgrades, but not downgrades. Suppose that we have:
If we start out by running require example.com v0.1.0 because that is the only If we then run require (
example.com v0.3.0
example.com/foo v0.2.0
) But now suppose that we want to get back to our initial state. If we run require (
example.com v0.1.0
example.com/foo v0.2.0
) and an ambiguous import. The user could perhaps resolve that by running |
One general approach might be:
|
As noted in #27858 (comment), when a package is moved between two modules that share one of the complete module paths as a prefix, each needs to
require
some baseline version of the other, for two reasons:To ensure that
go get -u
doesn't drop any needed packages.To ensure that any third module that depends on both of the common-prefix modules will always end up in a configuration that provides only one copy of each package.
It would be really unfortunate if moving a package meant that you could never run
go mod tidy
the involved modules again, or that you have to apply some manual edit every time you run it.We should either modify
go mod tidy
to avoid dropping requirements that are involved in a cycle with the main module, or add some explicit annotation comment to tell it not to drop an apparently-unnecessary requirement.The text was updated successfully, but these errors were encountered: