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

x/tools/gopls: add support for a target language version, and drop support for building at legacy Go versions #50825

Open
findleyr opened this issue Jan 26, 2022 · 5 comments
Labels
gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository.
Milestone

Comments

@findleyr
Copy link
Contributor

Background

Right now the gopls team supports building gopls using the four most recent major Go versions, though technically we still maintain support for Go 1.12+. This is significantly longer than the support window of the Go project itself, which covers only the two most recent major Go versions.

In the past, we've seen evidence (in the form of bug reports or survey results) that our users are supporting older Go versions for their applications/libraries. Whether or not this is a good thing is moot: there were reasons out of our control (e.g. cloud services support windows) that caused our users to support older Go versions. Absent a strong reason to break compatibility, the gopls team continued to maintain compatibility with older Go versions because the only way to provide accurate functionality for an older Go version was to build gopls at that Go version.

This legacy support causes significant friction for the team, notably:

  • we maintain additional CI (Kokoro) that runs tests using older Go versions
  • we work around issues that only occur with older Go versions
  • we will be maintaining a compatibility layer that replicates the functionality of go.work at older Go versions
  • our tests must be tolerant of error messages produced at older Go versions
  • some of our analyzers interpret error messages, and so must also be tolerant of error messages produced at older Go versions
  • we cannot easily leverage recent language or standard library improvements in our own code
  • our feedback cycle with the standard library is ~infinite: we cannot typically wait for fixes to go/parser or go/types
  • the dependencies we integrate with (e.g. gofumpt or staticcheck) have (quite reasonably) incompatible support windows

Proposal

We should provide features that make it easier to build gopls with a recent Go version but target development at an earlier Go version. We should then begin the process of dropping support for building gopls at older Go versions. As we do this, we should document and announce the final version of gopls that supports being built at each Go version.

Eventually we should align our support window with the Go project: the two most recent Go versions. This will allow us to turn down our legacy CI.

Supporting a target language version

With Go 1.18, the types.Config.GoVersion field allows us to specify an accepted language version for go/types, analogous to the compiler -lang flag. This removes a key blocker to this proposal.

Specifically, there are three components to providing accurate gopls functionality for older target Go versions:

  1. providing compiler (=go/types) errors based on the target language version (x/tools/gopls: set types.Config.GoVersion based on go.mod #50688)
  2. warning about usage of standard library APIs that were added after the target language version (x/tools/gopls: warn about standard library API usage based on Go version #50689)
  3. building packages based on the target language version (i.e. based on the correct release tags)

Of these, (1) and (2) are now straightforward, as described by the linked issues. (3) is harder, because AFAIK x/tools/go/packages (and the go command) does not provide a way to specify release tags -- they are baked into the go binary. Issue #42504 would be useful here: gopls could do its own post-processing of build tags.

In the meantime, we can either declare that we won't be able to satisfy (3), or support using a different go command for go/packages than was used to build gopls. In principle simply using a different go version for go list should work, but may introduce difficult combinatorial problems. Using a different version of go for go/packages would actually handle both (2) and (3) above, so we should explore this option.

We should of course update our installation instructions to document this workflow.

Deriving the target language version(s)

We can derive the target language version from the applicable go.mod, the go version in PATH, or from explicit gopls configuration. We may use more than one of these sources, but ideally we would avoid any additional gopls configuration.

Dropping support for older Go versions

We can take the following steps to ease the impact on our users when we drop support for a Go version:

  • Announce plans for final versions in our release notes. Specifically, since we try to release approximately monthly, we should endeavor to announce when the next version of gopls will be the final version to support being built at a given Go version.
  • Surface this information when upgrading gopls in VS Code.
  • Make VS Code aware of the gopls compatibility matrix, so that it doesn't try to upgrade to an unsupported version.
  • Explain all of this in our documentation.

CC @golang/tools-team

@gopherbot gopherbot added Tools This label describes issues relating to any tools in the x/tools repository. gopls Issues related to the Go language server, gopls. labels Jan 26, 2022
@gopherbot gopherbot added this to the Unreleased milestone Jan 26, 2022
@findleyr findleyr modified the milestones: Unreleased, gopls/on-deck Jan 26, 2022
@bcmills
Copy link
Contributor

bcmills commented Jan 26, 2022

Deriving the target language version(s)

(CC @dominikh @mvdan, assuming they are still interested in this topic.)

@mvdan
Copy link
Member

mvdan commented Sep 27, 2022

Deriving the target language version(s)

#55092 should definitely help here.

Eventually we should align our support window with the Go project: the two most recent Go versions. This will allow us to turn down our legacy CI.

I would personally support this. Anyone stuck on older and unsupported Go versions could similarly stick to a slightly older version of gopls, I would imagine. Perhaps any IDEs which try to automatically update Go and gopls could learn about this too.

It's also worth noting that this "supporting two Go versions" policy is pretty standard elsewhere, including the dependencies of gopls like gofumpt. I just tagged v0.4.0 and it supports Go 1.18 or later, for example, which now I'm thinking might be a problem for gopls to update if it aims to support four releases for a bit longer.

@gopherbot
Copy link

Change https://go.dev/cl/435356 mentions this issue: go/packages: warn if 'go list' on PATH is too new

@findleyr
Copy link
Contributor Author

@mvdan

I just tagged v0.4.0 and it supports Go 1.18 or later, for example, which now I'm thinking might be a problem for gopls to update if it aims to support four releases for a bit longer.

Not a problem. This has happened in the past, and we simply don't link gofumpt at older Go versions (similar for staticcheck).

gopherbot pushed a commit to golang/tools that referenced this issue Sep 28, 2022
An application that links in version 1.18 of (say)
go/types cannot process Go source files reported
by version 1.19 of 'go list'. There is no way to
tell go list to behave as if it was go1.18, so
for now we proceed with parsing/typechecking but,
in case of errors, we issue an additional informative
diagnostic.

Fixes golang/go#55883
Fixes golang/go#55045
Updates golang/go#50825
Updates golang/go#52078

Change-Id: I5fd99b09742c136f4db7f71d2a75e4cdb730460d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/435356
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Alan Donovan <adonovan@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
@gopherbot
Copy link

Change https://go.dev/cl/439836 mentions this issue: gopls/internal/lsp: warn about Go versions that are too old

gopherbot pushed a commit to golang/tools that referenced this issue Oct 7, 2022
Add a showMessage notification when the Go version in PATH is too old.

Also delete the unused View.Rebuild method.

Updates golang/go#50825

Change-Id: I279a04f021a0f8ddb09fcfe299fbab8d10e8c022
Reviewed-on: https://go-review.googlesource.com/c/tools/+/439836
Run-TryBot: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests

4 participants