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:
providing compiler (=go/types) errors based on the target language version (#50688)
warning about usage of standard library APIs that were added after the target language version (#50689)
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.
The text was updated successfully, but these errors were encountered:
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
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:
go.work
at older Go versionsgo/parser
orgo/types
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 forgo/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:
go/types
) errors based on the target language version (#50688)Of these, (1) and (2) are now straightforward, as described by the linked issues. (3) is harder, because AFAIK
x/tools/go/packages
(and thego
command) does not provide a way to specify release tags -- they are baked into thego
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 forgo/packages
than was used to build gopls. In principle simply using a differentgo
version forgo list
should work, but may introduce difficult combinatorial problems. Using a different version ofgo
forgo/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
, thego
version inPATH
, 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:
CC @golang/tools-team
The text was updated successfully, but these errors were encountered: