-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
With the compiler type checker being rewritten based on go/types in cmd/compile/internal/types2, certain compiler features have been ported back to go/types. One such feature is the types.Config.goVersion field, which configures the target Go version being type checked, necessary for the -lang compiler flag. This issue proposes to export that field in go/types as types.Config.GoVersion. I think this could be a valuable change, but am not 100% confident that we should make it, so the purpose of this proposal is to hopefully start a discussion and get feedback.
Specifically, the GoVersion field could be set to a valid Go version string (e.g. "go1.N") to instruct the type checker to disallow language features that were added after Go 1.N. Note that this wouldn't prevent importing standard library APIs that were added after Go 1.N, with the exception of unsafe -- that would be the domain of the importer.
This may be particularly relevant with the large number of language changes landing for generics. Generics both introduce a large change to the type checker, and incentivize tools to break compatibility with older Go versions so that they can leverage generics in their own code.
In general there are always users whose deployment targets are bound to older Go versions, for a variety of reasons. It would be good if their tooling were not bound by the same constraint. Adding the types.Config.GoVersion field seems like a necessary (though not always sufficient) mechanism to avoid such coupling.
The only downside that I can see to this new API is that go/types will have to continue to support older versions of the language. But this is essentially already the case since we want go/types and cmd/compile/internal/types2 to stay in sync (and maybe even converge in some areas). New language features are by definition additive, so maintaining support for older versions Go is usually as simple as a version check and error message.
But this is not a change that should be made casually, as it signals a new model which, if endorsed, should be supported by other go/* packages. If there is consensus that this is a good direction to head, I will open a similar issue for go/parser, but I am holding off on this so as not to fragment discussion about the overall concept. I'm curious what other members of the tools community think: is this a universally good change? How valuable would it be?
CC @dominikh @mvdan: I know staticcheck and gofumpt already have a concept of target version, so perhaps you have an opinion on this change.