-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
What version of Go are you using (go version
)?
$ go version go version go1.12 darwin/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GOARCH="amd64" GOBIN="" GOCACHE="/Users/cbro/Library/Caches/go-build" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOOS="darwin" GOPATH="/Users/cbro/" GOPROXY="" GORACE="" GOROOT="/Users/cbro/sdk/go1.12" GOTMPDIR="" GOTOOLDIR="/Users/cbro/sdk/go1.12/pkg/tool/darwin_amd64" GCCGO="gccgo" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/var/folders/h0/kdykkxh94y1fdv1_yz98yr_w003lw8/T/tmp.ULmCh1W7/go.mod" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/h0/kdykkxh94y1fdv1_yz98yr_w003lw8/T/go-build671297704=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
While investigating googleapis/google-cloud-go#1359, golang/lint#436, and opening census-instrumentation/opencensus-go#1064, I've found it impossible to figure out how to get almost any of these packages to build and successfully run go get -u
.
It seems to be a never-ending loop of things depending on slightly older things, which ultimately end up depending on the invalid github.com/golang/lint.
For a lot, but not all (see below) of these packages, I was able to track the chain from github.com/golang/lint up to its depender using go mod graph
.
Of course, because of MVS, the old version of grpc (and therefore github.com/golang/lint) is never used in the actual build, but for some reason still blocks a successful run of go get -u
.
$ cd $(mktemp -d)
T/tmp.ULmCh1W7 $ ls
T/tmp.ULmCh1W7 $ go mod init m
go: creating new go.mod: module m
T/tmp.ULmCh1W7 $ go get google.golang.org/grpc
go: downloading golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
go: downloading google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
go: extracting golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
go: downloading golang.org/x/text v0.3.0
go: extracting google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
go: extracting golang.org/x/text v0.3.0
T/tmp.ULmCh1W7 $ cat go.mod
module m
go 1.12
require google.golang.org/grpc v1.19.0 // indirect
T/tmp.ULmCh1W7 $ go get -u
go: finding github.com/golang/glog latest
go: finding google.golang.org/genproto latest
go: finding golang.org/x/sync latest
go: finding honnef.co/go/tools latest
go: finding golang.org/x/lint latest
go: finding golang.org/x/oauth2 latest
go: finding golang.org/x/net latest
go: finding golang.org/x/sys latest
go: finding github.com/shurcooL/issuesapp latest
go: finding github.com/google/pprof latest
go: finding golang.org/x/time latest
go: finding golang.org/x/exp latest
go: finding github.com/anmitsu/go-shlex latest
go: finding golang.org/x/tools latest
go: finding github.com/shurcooL/issues latest
go: finding github.com/tarm/serial latest
go: finding golang.org/x/build latest
go: finding github.com/neelance/astrewrite latest
go: finding dmitri.shuralyov.com/state latest
go: finding github.com/shurcooL/httpgzip latest
go: finding github.com/shurcooL/gopherjslib latest
go: finding github.com/shurcooL/htmlg latest
go: finding github.com/shurcooL/component latest
go: finding github.com/google/btree latest
go: finding github.com/shurcooL/reactions latest
go: finding github.com/shurcooL/github_flavored_markdown latest
go: finding github.com/jellevandenhooff/dkim latest
go: finding grpc.go4.org latest
go: finding github.com/shurcooL/highlight_go latest
go: finding dmitri.shuralyov.com/html/belt latest
go: finding go4.org latest
go: finding github.com/shurcooL/notifications latest
go: finding github.com/shurcooL/users latest
go: finding github.com/coreos/go-systemd latest
go: finding golang.org/x/mobile latest
go: finding github.com/BurntSushi/xgb latest
go: finding github.com/shurcooL/webdavfs latest
go: finding github.com/neelance/sourcemap latest
go: finding github.com/shurcooL/go latest
go: finding golang.org/x/crypto latest
go: finding github.com/prometheus/client_model latest
go: finding github.com/flynn/go-shlex latest
go: finding golang.org/x/perf latest
go: finding github.com/prometheus/procfs latest
go: finding dmitri.shuralyov.com/service/change latest
go: finding github.com/jstemmer/go-junit-report latest
go: finding github.com/shurcooL/httpfs latest
go: finding github.com/shurcooL/httperror latest
go: finding github.com/sourcegraph/syntaxhighlight latest
go: finding github.com/beorn7/perks latest
go: finding gopkg.in/check.v1 latest
go: finding github.com/gopherjs/gopherjs latest
go: finding dmitri.shuralyov.com/app/changes latest
go: finding github.com/shurcooL/highlight_diff latest
go: finding github.com/shurcooL/home latest
go: finding github.com/shurcooL/octicon latest
go: finding github.com/sourcegraph/annotate latest
go: finding github.com/gonum/blas latest
go: finding github.com/gonum/internal latest
go: finding github.com/gonum/lapack latest
go: finding github.com/GoogleCloudPlatform/cloudsql-proxy latest
go: finding github.com/gregjones/httpcache latest
go: finding golang.org/x/image latest
go: finding github.com/shurcooL/events latest
go: finding github.com/bradfitz/go-smtpd latest
go: finding github.com/shurcooL/go-goon latest
go: finding github.com/shurcooL/gofontwoff latest
go: finding github.com/golang/lint latest
go: finding github.com/alecthomas/units latest
go: finding github.com/gonum/matrix latest
go: github.com/golang/lint@v0.0.0-20190313153728-d0100b6bd8b3: parsing go.mod: unexpected module path "golang.org/x/lint"
go: finding github.com/eapache/go-xerial-snappy latest
go: finding github.com/mwitkow/go-conntrack latest
go: finding github.com/rcrowley/go-metrics latest
go: finding github.com/aclements/go-moremath latest
go: finding github.com/gonum/floats latest
go get: error loading module requirements
Exit code 1
T/tmp.ULmCh1W7 $ go mod graph | grep golang/lint
Exit code 1
T/tmp.ULmCh1W7 $ go mod graph
m google.golang.org/grpc@v1.19.0
google.golang.org/grpc@v1.19.0 cloud.google.com/go@v0.26.0
google.golang.org/grpc@v1.19.0 github.com/BurntSushi/toml@v0.3.1
google.golang.org/grpc@v1.19.0 github.com/client9/misspell@v0.3.4
google.golang.org/grpc@v1.19.0 github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b
google.golang.org/grpc@v1.19.0 github.com/golang/mock@v1.1.1
google.golang.org/grpc@v1.19.0 github.com/golang/protobuf@v1.2.0
google.golang.org/grpc@v1.19.0 golang.org/x/lint@v0.0.0-20181026193005-c67002cb31c3
google.golang.org/grpc@v1.19.0 golang.org/x/net@v0.0.0-20180826012351-8a410e7b638d
google.golang.org/grpc@v1.19.0 golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be
google.golang.org/grpc@v1.19.0 golang.org/x/sync@v0.0.0-20180314180146-1d60e4601c6f
google.golang.org/grpc@v1.19.0 golang.org/x/sys@v0.0.0-20180830151530-49385e6e1522
google.golang.org/grpc@v1.19.0 golang.org/x/text@v0.3.0
google.golang.org/grpc@v1.19.0 golang.org/x/tools@v0.0.0-20190114222345-bf090417da8b
google.golang.org/grpc@v1.19.0 google.golang.org/appengine@v1.1.0
google.golang.org/grpc@v1.19.0 google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8
google.golang.org/grpc@v1.19.0 honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099
What did you expect to see?
go get -u
succeeds, no mention of github.com/golang/lint because it shouldn't be included due to MVS rules.
Activity
broady commentedon Mar 14, 2019
My theory (sorry, it's late, so not sure if it's obviously right or wrong... also, this bug report is poorly written but I'm pretty frustrated and confused by all of this)
Because we are allowed circular dependencies on modules, we have two libraries:
A@0.1 requires github.com/golang/lint
A@0.1 requires B@v0.0.0-...
B@0.1 requires A@0.1
A fixes its import to golang.org/x/lint, tags 0.2
B@0.2 updates its A dependency, and now requires A@0.2.
But A@0.2 still requires B@0.1 which requires A@0.1 which requires B@v0.0.0-... which requires github.com/golang/lint.
Of course, due to MVS, we only choose one version of the dependency at build time. However,
go get -u
doesn't seem to use MVS in the same way. It appears to touch every single version in the never-ending chain of dependent versions, even if they aren't used in the actual build.So the only to break this cycle is to simultaneously tag new versions of A and B, and have them require each other. (incompatible with CI)
In reality, we have more than just two things depending on each other, there's far more. golang.org/x/oauth2, google.golang.org/api/grpc, cloud.google.com/go, google.golang.org/api, go.opencensus.io basically all have dependencies on each other.
dmitshur commentedon Mar 14, 2019
/cc @bcmills
We've discussed this general issue today (or yesterday) and Bryan said he might be aware of a fix that can be applied to
cmd/go
to make the situation better. I'll let him provide more information on that.broady commentedon Mar 14, 2019
Something along the lines of this, maybe? (see patch below)
Tests don't pass, though, so this is probably not sane.
The idea is to not try to upgrade something when we already use a newer version. Theory: upgrading from 0.2 to 0.3 is less work than 0.1 to 0.3, and there's no need to check the same package if you already checked a newer version.
edit: ah, yes, theory and tests fail because vN+1 may have downgraded one of its deps.
Simplified problem...
M has a requirement on A@0.1 and B@0.1
B@0.1 has a requirement on C@0.1
B@0.2 dropped the requirement on C entirely
A@0.1 has a requirement on B@0.2
"go get -u" still tries to upgrade C, because of M's dependency on B@0.1, even though M won't use B@0.1 or C@0.1 in the build at all, only A@0.1 and B@0.2.
Another ecosystem problem is "indirect" entries in go.mod. As evidenced by zipkin including an indirect entry in github.com/golang/lint:
A@0.1 requires C@0.0
B@0.1 requires A@0.1 and adds an indirect entry to C@0.0
A@0.2 drops the C requirement.
M requires A@0.2 and B@0.1, indirectly depending on C@0.0 even though it isn't used to build, because MVS upgrades B's A@0.1 requirement to A@0.2.
In this case, A = grpc or genproto, B = zipkin, C = github.com/golang/lint
[-]cmd/go: unexpected module path but no entry in graph[/-][+]cmd/go: "get -u" too many required modules are attempted for upgrade[/+]thepudds commentedon Mar 14, 2019
FWIW, I also suspect (a) something is wrong here, or (b) that the behavior here can be improved.
Potentially related is #30455 (comment), which asks if
golang.org/x/lint
vs.github.com/golang/lint
could be viewed as a non-fatal error:Also potentially related:
[-]cmd/go: "get -u" too many required modules are attempted for upgrade[/-][+]cmd/go: "get -u" stumbles over github.com/golang/lint[/+]rsc commentedon Mar 14, 2019
Leaving the "too much upgrading" problem for #26902.
Retitled this to be about lint since that is the specific complaint in "what did you expect to see?".
It seems like we need a clear signal from the upgraded module that "I used to be this old name". And then if you are resolving the old name and land in the new module claiming "I used to be this old name", the build would automatically interpret the old name as the new name. Maybe that's a per-module signal; maybe it's a per-package signal. It needs to be an explicit signal, though. It's not enough to just "find code at X that seems to be module Y so pretend X means Y" because that breaks people who github fork X into their own account as Y. In that case we don't want go get of the fork to silently redirect back to the original.
dmitshur commentedon Mar 14, 2019
This requires the upgraded module to know its old name. In this specific case, it might be possible, because the canonical import path of lint used to be
github.com/golang/lint
a long time ago (see here.However, it didn't start enforcing import paths until much later (via import comment for GOPATH mode, and via go.mod file for module mode), so some projects may have started importing it via any other alias, not just
github.com/golang/lint
.Should it be responsibility of an upgraded module to know what were all the non-canonical import paths that some projects in the wild may have imported it as?
bcmills commentedon Mar 14, 2019
In general that set is well-defined: we must have arrived at the repository somehow (via redirects), so the only possible names for it are things that redirect to it. I would guess that it's pretty rare for folks to set up redirectors for arbitrary repositories just to use them via different import paths.
thepudds commentedon Mar 14, 2019
One short description of the build list (from the cmd/go documentation) is:
It is unlikely that I will describe this exactly correctly, but from the outside it seems that if the inconsistency between
golang.org/x/lint
vs.github.com/golang/lint
could be viewed as a non-fatal error, it could mean that the particular problematic version of the consumer does not get added to the candidate build list being iteratively built up. In other words, don't add the the version of the consumer with the import ofgithub.com/golang/lint
because that version of the consumer has an error, but that error is not fatal to the overall build.Or maybe that is not the right way to think about it -- maybe instead the "bad" consumer version gets added to the build list but is marked that it is bad, but that is not a fatal problem for the overall build as long as the bad version is not the version that gets selected in the end.
It seems some type of approach along those line would have solved the original
x/lint
issue reported in golang/lint#436 (givengoogle.golang.org/grpc@v1.16.0
was the "bad" version that imported the wrong flavor oflint
, but there were otherrequire
statements forv1.17.0
,v1.18.0
forgrpc
in the overall build and hence thev1.16.0
ofgrpc
was not going to be selected anyway). Perhaps that would also help the more recent incarnation being reported here by @broady.Edit: part of the problem with the current behavior is the degree to which old problems that were fixed a while ago are still a "hangover" for right now. E.g.,
grpc
I think fixed the lint problem in its owngo.mod
over 4 months ago and released multiple releases since, and it seems a healthy portion of the ecosystem has started using those newer releases ofgrpc
... but one laggardgrpc
consumer seems to be fatal right now (which seems to be in contrast to how usually in a modules world "laggards" are gently pulled forward by the rest of the ecosystem over time).77 remaining items
bcmills commentedon Mar 15, 2024
We've given this issue a lot of thought over the last several years. The current best-practice solution for changing a module's import path is to choose at least one of:
Optionally, also leave behind packages in a repo at the old path containing declarations that merely alias (or forward function calls) to the packages at the new path.
[-]cmd/go: "get -u" stumbles over repos imported via non-canonical paths[/-][+]cmd/go: more graceful upgrades when a module changes its name[/+]seankhliao commentedon Dec 2, 2024
related #70443