Reconciling Go deprecation delays with Staticcheck's minimum Go version
We’ve sent the following email to golang-dev, explaining our problem:
The Go project has the following policy regarding deprecating API1:
> If function F1 is being replaced by function F2 and the first > release in which F2 is available is Go 1.N, then an official > deprecation notice for F1 should not be added until Go 1.N+2. This > ensures that Go developers only see F1 as deprecated when all > supported Go versions include F2 and they can easily switch.
Staticcheck has a check that flags the use of deprecated API, using the deprecation markers to find said API. No other things considered, users using at least Go 1.N+2 will have their uses of F1 get flagged. If we assume that users of Go 1.N+2 want to support Go 1.N to Go 1.N+2, that works fine.
However, Staticcheck also has the notion of a minimum targeted Go version. This defaults to the Go version specified in go.mod, but can also be provided explicitly. This way, Staticcheck’s users can support however few or many older versions they want, and Staticcheck won’t make suggestions that don’t apply to the minimum version.
For deprecations, we maintain a mapping of deprecated API to when it was officially deprecated, i.e. when the marker was added. We also track when alternative API has first become available. For example, for F1 we would track (1.N+2, 1.N). When the user uses F1 and targets a minimum Go version new enough to have F2, we will flag the use of F1. This, however, has a nasty flaw: we still rely on seeing the deprecation notice to know that API is deprecated. This means that someone using Go 1.N+2 and targeting Go 1.N+1 will see F1 as deprecated, but someone using Go 1.N+1 and targeting Go 1.N+1 will not, because there’s no marker yet. This has caused inconsistencies between users’ machines and CI environments.
If I remove the “alternative available since” logic outright, then the combination of Go delaying adding markers and Staticcheck targeting a minimum Go version will lead to twice the delay before deprecated API gets flagged. Users will generally only start targeting Go 1.N+2 as the minimum once Go 1.N+4 has been released. Alternatively, I could stop relying on the markers altogether, maintain my own list of deprecated API, and preempt Go’s decision to add the marker by two versions. I don’t think that’s tenable. I would have to be aware of API to be deprecated in the future, and I would have to come up with my own deprecation messages.
Summarizing, both Go and Staticcheck try not to warn users too early, the combination of which either leads to twice the delay, or requires flawed workarounds.
Do you have any idea how to resolve this issue?
P.S.: the wiki says Go 1.N+2, but shouldn’t it actually be Go 1.N+1? Go supports the current and the previous release of Go; Go 1.N+1 would cover both supported versions.