Aligning Staticcheck's behavior with Go's deprecation policy

257 views
Skip to first unread message

Dominik Honnef (dominikh)

unread,
Jan 5, 2023, 5:51:19 PM1/5/23
to golang-dev
The Go project has the following policy regarding deprecating API[1]:

> 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.

[1]: https://github.com/golang/go/wiki/Deprecated

Ian Lance Taylor

unread,
Jan 5, 2023, 6:13:41 PM1/5/23
to Dominik Honnef (dominikh), golang-dev
On Thu, Jan 5, 2023 at 2:51 PM Dominik Honnef (dominikh)
<dominik...@gmail.com> wrote:
>
> 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.

Does it help that as of the upcoming Go 1.12 $GOROOT/api includes
information about all deprecated symbols and the release in which they
were deprecated?

Ian

Russ Cox

unread,
Jan 6, 2023, 11:42:11 AM1/6/23
to Dominik Honnef (dominikh), golang-dev
On Thu, Jan 5, 2023 at 5:51 PM Dominik Honnef (dominikh) <dominik...@gmail.com> wrote:
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.

I agree that it seems like N+1 should suffice. I have been taking the improv "yes and" / Chesterton's fence approach of accepting the N+2 unless it (a) turns out to be very important to cut back to N+1 and (b) we understand why it says N+2 and why that rationale no longer applies. If someone wants to figure out why it says N+2, please feel free. :-)

Best,
Russ

Filippo Valsorda

unread,
Jan 6, 2023, 12:04:58 PM1/6/23
to golang-dev
It seems to originate from this comment by Ian, which as far as I can tell gives the rationale for N+1, not N+2. It might be an off-by-one, or have gotten mixed up with the go line in go.mod meaning N-1 is supported? Ian?

Ian Lance Taylor

unread,
Jan 6, 2023, 1:38:33 PM1/6/23
to Filippo Valsorda, golang-dev
Thanks for the link. I don't understand that comment I wrote at all.

I agree that if a replacement is available in 1.N, then we can
deprecate the old approach in 1.N+1.

Ian
Reply all
Reply to author
Forward
0 new messages