gopls version
Build info
----------
golang.org/x/tools/gopls v0.20.0
golang.org/x/tools/gopls@v0.20.0 h1:fxOYZXKl6IsOTKIh6IgjDbIDHlr5btOtOUkrGOgFDB4=
github.com/BurntSushi/toml@v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/fatih/camelcase@v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/gomodifytags@v1.17.1-0.20250423142747-f3939df9aa3c h1:dDSgAjoOMp8da3egfz0t2S+t8RGOpEmEXZubcGuc0Bg=
github.com/fatih/structtag@v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fsnotify/fsnotify@v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/google/go-cmp@v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
golang.org/x/exp/typeparams@v0.0.0-20250620022241-b7579e27df2b h1:KdrhdYPDUvJTvrDK9gdjfFd6JTk8vA1WJoldYSi0kHo=
golang.org/x/mod@v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
golang.org/x/sync@v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sys@v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/telemetry@v0.0.0-20250710130107-8d8967aff50b h1:DU+gwOBXU+6bO0sEyO7o/NeMlxZxCZEvI7v+J4a1zRQ=
golang.org/x/text@v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/tools@v0.35.1-0.20250728180453-01a3475a31bc h1:ZRKyKRJl/YEWl9ScZwd6Ua6xSt7DE6tHp1I3ucMroGM=
golang.org/x/vuln@v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
honnef.co/go/tools@v0.7.0-0.dev.0.20250523013057-bbc2f4dd71ea h1:fj8r9irJSpolAGUdZBxJIRY3lLc4jH2Dt4lwnWyWwpw=
mvdan.cc/gofumpt@v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k=
mvdan.cc/xurls/v2@v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=
go: go1.24.6
go env
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN='/home/caleb/bin'
GOCACHE='/home/caleb/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/caleb/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3694712078=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/caleb/w/liftoff/go.mod'
GOMODCACHE='/home/caleb/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/caleb/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/caleb/3p/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/caleb/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/caleb/3p/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.1'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
(This seems very similar to, or perhaps a dupe of, #40278, judging by the description. However, gopls definitely doesn't seem to do what is described there.)
It's unfortunately quite common that I need to deal with packages with name collisions. The main offender is cmp
and github.com/google/go-cmp/cmp
, though there are some others as well.
When I encounter this situation, gopls is much less helpful than it normally is when dealing with non-colliding packages:
- Once I've imported one package, I can't get completions about names for the other package.
- Once I've imported one package, gopls doesn't add the colliding package import. I need to manually add the import with an alias.
Here is a concrete scenario: I create a file that imports cmp
. (Let's say it uses cmp.Or
somewhere.)
What did you see happen?
If I type cmp.
and then invoke completion, I only get suggestions from the stdlib's cmp
package. If I type cmp.Di
and invoke completion, there are no suggestions, even though go-cmp
is a dependency of my module. If I type cmp.Diff
and hit save, it's just a compile error; no import is added.
What did you expect to see?
It would be nice if gopls helped me here. For example:
- If I type
cmp.Di
, it could show meDiff
as a completion since that's available from a differentcmp
than thecmp
I already have imported into my package. - If I type
cmp.Diff
and hit save, it could realize that because I'm referring to a differentcmp
than the one I've imported, it should importgithub.com/google/go-cmp/cmp
, give it an alias (saygocmp
), and then change my text togocmp.Diff
.
There are probably some other ways for this UX to work. I'd just like to avoid needing to manually add the import and alias.
Furthermore, I'd like to be able to provide gopls with my preferences about standard collision resolution. When cmp
and github.com/google/go-cmp/cmp
are both imported, I always want the latter to be aliased as gocmp
, regardless of which import was added first.
Editor and settings
I'm using neovim and its LSP support.
Logs
This is a feature request, not a bug report, but I can capture logs if you want. There's nothing interesting or unexpected there AFAICT.
Comment From: findleyr
Remilestoning for the backlog, I think this has been a long-standing missing feature. However, I do think it's a good idea.
@pjweinb I know you've looked at the goimports code recently. Perhaps this is just a trivial extension of its resolution logic?
Comment From: pjweinb
I'll look at it. If one types cmp.
it will probably offer stdlib choices, but if one types cmp.D
it should realize that there's no match in the stdlib, and look harder. And I'll look at https://github.com/golang/go/issues/40278 too, which looks like it aged out.