1 <ul class="changes-toc">
2 <li><a href="#performance-improvements">Performance improvements</a></li>
3 <li><a href="#unused">Changes to the detection of unused code</a><ul>
4 <li><a href="#unused-whole-program">Removal of whole-program mode and changes to the handling of exported identifiers</a></li>
5 <li><a href="#unused-improvements">Improvements</a></li>
7 <li><a href="#ui-improvements">UI improvements</a></li>
8 <li><a href="#versioning-improvements">Changes to versioning scheme</a></li>
9 <li><a href="#checks">Checks</a><ul>
10 <li><a href="#checks-new">New checks</a></li>
11 <li><a href="#checks-changed">Changed checks</a></li>
13 <li><a href="#2020.2.1">Staticcheck 2020.2.1 release notes</a></li>
16 <h2 id="performance-improvements">Performance improvements</h2>
19 The primary focus of this release is a major improvement in performance, significantly reducing memory usage while also reducing runtimes.
22 <details style="margin-bottom: 1em;">
23 <summary>Benchmarks comparing the previous and current releases of Staticcheck</summary>
26 <caption>Uncached, GOMAXPROCS=1</caption>
43 <td>p=0.000, n=10+10</td>
47 <td>k8s.io/kubernetes/pkg/... </td>
51 <td>p=0.000, n=10+10</td>
59 <td>p=0.000, n=8+10</td>
67 <td>p=0.000, n=9+10</td>
75 <td>p=0.001, n=10+10</td>
85 <td>p=0.043, n=10+10</td>
89 <td>k8s.io/kubernetes/pkg/... </td>
93 <td>p=0.000, n=10+10</td>
101 <td>p=0.000, n=10+10</td>
109 <td>p=0.000, n=8+10</td>
117 <td>p=0.063, n=10+10</td>
122 <table class="table">
123 <caption>Cached, GOMAXPROCS=1</caption>
137 <td>image/color </td>
141 <td>p=0.000, n=8+10</td>
145 <td>k8s.io/kubernetes/pkg/... </td>
149 <td>p=0.000, n=9+10</td>
157 <td>p=0.000, n=8+8</td>
165 <td>p=0.000, n=10+9</td>
173 <td>p=0.000, n=10+10</td>
179 <td>image/color </td>
180 <td>38.6MB ± 4% </td>
181 <td>20.8MB ± 1% </td>
183 <td>p=0.000, n=9+10</td>
187 <td>k8s.io/kubernetes/pkg/... </td>
191 <td>p=0.000, n=10+10</td>
196 <td>70.5MB ± 5% </td>
197 <td>25.8MB ± 2% </td>
199 <td>p=0.000, n=10+9</td>
207 <td>p=0.000, n=10+10</td>
212 <td>37.2MB ± 2% </td>
213 <td>21.3MB ± 1% </td>
215 <td>p=0.000, n=9+10</td>
220 <table class="table">
221 <caption>Uncached, GOMAXPROCS=32</caption>
235 <td>image/color </td>
239 <td>p=0.115, n=10+8</td>
243 <td>k8s.io/kubernetes/pkg/... </td>
247 <td>p=0.000, n=10+10</td>
255 <td>p=0.870, n=10+10</td>
263 <td>p=0.000, n=10+9</td>
271 <td>p=0.753, n=10+10</td>
277 <td>image/color </td>
281 <td>p=0.515, n=8+10</td>
285 <td>k8s.io/kubernetes/pkg/... </td>
286 <td>5.77GB ± 6% </td>
287 <td>2.76GB ± 4% </td>
289 <td>p=0.000, n=10+10</td>
297 <td>p=0.000, n=10+10</td>
302 <td>1.74GB ±10% </td>
303 <td>1.15GB ±14% </td>
305 <td>p=0.000, n=10+10</td>
313 <td>p=0.579, n=10+10</td>
319 <table class="table">
320 <caption>Cached, GOMAXPROCS=32</caption>
334 <td>image/color </td>
335 <td>96.0ms ± 6% </td>
336 <td>80.0ms ± 0% </td>
338 <td>p=0.000, n=10+9</td>
342 <td>k8s.io/kubernetes/pkg/... </td>
346 <td>p=0.000, n=9+8</td>
354 <td>p=0.000, n=10+10</td>
362 <td>p=0.000, n=10+10</td>
370 <td>p=0.000, n=9+10</td>
376 <td>image/color </td>
377 <td>46.4MB ± 3% </td>
378 <td>24.1MB ± 5% </td>
380 <td>p=0.000, n=8+10</td>
384 <td>k8s.io/kubernetes/pkg/... </td>
385 <td>1.38GB ± 9% </td>
386 <td>0.27GB ± 1% </td>
388 <td>p=0.000, n=10+10</td>
393 <td>80.7MB ±12% </td>
394 <td>31.4MB ± 2% </td>
396 <td>p=0.000, n=10+8</td>
404 <td>p=0.000, n=10+10</td>
409 <td>48.5MB ± 6% </td>
410 <td>24.4MB ± 3% </td>
412 <td>p=0.000, n=10+10</td>
419 See <a href="https://github.com/dominikh/go-tools/commit/5cfc85b70e7b778eb76fd7338e538d7c9af21e4e">commit 5cfc85b70e7b778eb76fd7338e538d7c9af21e4e</a>
420 for details on how these improvements have been achieved.
424 Furthermore, Staticcheck 2020.2 will skip very large packages (currently packages that are 50 MiB or larger),
425 under the assumption that these packages contain bundled assets and aren't worth analyzing.
426 This might further reduce Staticcheck's memory usage in your projects.
429 <h2 id="unused">Changes to the detection of unused code</h2>
431 <h3 id="unused-whole-program">Removal of whole-program mode and changes to the handling of exported identifiers</h3>
433 The <a href="#performance-improvements">aforementioned performance improvements</a> necessitate some changes to the <em>U1000</em> check (also known as <em>unused</em>).
437 The most visible change is the removal of the <em>whole program</em> mode.
438 This mode, which analyzed an entire program and reported unused code even if it is exported,
439 did not work well with the kind of caching that we use in Staticcheck.
440 Even in previous versions, it didn't always work correctly and may have caused flaky results,
441 depending on the state of the cache and the order of <code>staticcheck</code> invocations.
445 The whole-program mode may be revived in the future as a standalone tool,
446 with the understanding that this mode of operation is inherently more expensive than <code>staticcheck</code>.
447 In the meantime, if you depend on this functionality and can tolerate its bugs, you should continue using Staticcheck 2020.1.
451 As part of improving the correctness of U1000, changes were made to the normal mode as well.
452 In particular, <strong>all</strong> exported package-level identifiers will be considered used from now on,
453 even if these identifiers are declared in <code>package main</code> or tests, even if they are otherwise unused.
454 Exported identifiers in <code>package main</code> can be used in ways invisible to us, for example via the <code>plugin</code> build mode.
455 For tests, we would run into the same kind of issues as we did with the whole program mode.
458 <h3 id="unused-improvements">Improvements</h3>
461 The <code>//lint:ignore</code> directive now works more intelligently with the U1000 check.
462 In previous versions, the directive would only suppress the output of a diagnostic. For example, for the following example
465 <pre><code>package pkg
467 //lint:ignore U1000 This is fine.
470 func fn2() {}</code></pre>
473 Staticcheck would emit the following output:
476 <pre><samp>foo.go:6:6: func fn2 is unused (U1000)</samp></pre>
479 as it would only suppress the diagnostic for <code>fn1</code>.
483 Beginning with this release, the directive instead actively marks the identifier as used,
484 which means that any transitively used code will also be considered used, and no diagnostic will be reported for <code>fn2</code>.
485 Similarly, the <code>//lint:file-ignore</code> directive will consider everything in a file used, which may transitively mark code in other files used, too.
488 <h2 id="ui-improvements">UI improvements</h2>
490 We've made some minor improvements to the output and behavior of the <code>staticcheck</code> command:
493 <li>the command now prints instructions on how to look up documentation for checks</li>
494 <li>output of the <code>-explain</code> flag includes a link to the online documentation</li>
495 <!-- <li>the <code>-f</code> flag gets validated <em>before</em> analyzing packages</li> -->
496 <li>a warning is emitted when a package pattern matches no packages</li>
497 <li>unmatched ignore directives cause <code>staticcheck</code> to exit with a non-zero status code</li>
500 <h2 id="versioning-improvements">Changes to versioning scheme</h2>
503 Staticcheck releases have two version numbers: one meant for human consumption and one meant for consumption by machines, via Go modules.
504 For example, the previous release was both <code>2020.1.6</code> (for humans) and <code>v0.0.1-2020.1.6</code> (for machines).
508 In previous releases, we've tried to include the human version in the machine version, by using the <code>v0.0.1-<human version></code> scheme.
509 However, this scheme had various drawbacks.
510 For this and future releases we've switched to a more standard scheme for machine versions: <code>v0.<minor>.<patch></code>.
511 Minor will increase by one for every feature release of Staticcheck,
512 and patch will increase by one for every bugfix release of Staticcheck,
513 resetting to zero on feature releases.
517 For example, this release is both <code>2020.2</code> and <code>v0.1.0</code>.
518 A hypothetical <code>2020.2.1</code> would be <code>v0.1.1</code>, and <code>2021.1</code> will be <code>v0.2.0</code>.
519 This new versioning scheme fixes various issues when trying to use Staticcheck as a Go module.
520 It will also allow us to make true pre-releases in the future.
524 Documentation on the website, as well as the output of <code>staticcheck -version</code>, will include both version numbers, to make it easier to associate the two.
528 For detailed information on how we arrived at this decision, see the discussion on <a href="https://github.com/dominikh/go-tools/issues/777">issue 777</a>.
531 <h2 id="checks">Checks</h2>
532 <h3 id="checks-new">New checks</h3>
535 The following new checks have been added:
539 <li>{{ check "SA4023" }} flags impossible comparisons of interface values with untyped nils</li>
540 <li>{{ check "SA5012" }} flags function calls with slice arguments that aren't the right length</li>
541 <li>{{ check "SA9006" }} flags dubious bit shifts of fixed size integers</li>
544 <h3 id="checks-changed">Changed checks</h3>
547 Several checks have been improved:
551 <li>{{ check "S1030" }} no longer recommends replacing <code>m[string(buf.Bytes())]</code> with <code>m[buf.String()]</code>, as the former gets optimized by the compiler</li>
552 <li>{{ check "S1008" }} no longer incorrectly suggests that the negation of <code>>=</code> is <code><=</code></li>
553 <li>{{ check "S1029" }} and {{ check "SA6003" }} now also check custom types with underlying type <code>string</code></li>
554 <li>{{ check "SA1019" }} now recognizes deprecation notices that aren't in the last paragraph of a comment</li>
555 <li>{{ check "SA1019" }} now emits more precise diagnostics for deprecated code in the standard library</li>
556 <li>{{ check "SA4006" }} no longer flags assignments where the value is a typed nil</li>
557 <li>{{ check "SA5011" }} is now able to detect more functions that never return, thus reducing the number of false positives</li>
558 <li>{{ check "SA9004" }} no longer assumes that constants belong to the same group when they have different types</li>
559 <li>Automatic fixes for {{ check "SA9004" }} inside gopls no longer incorrectly duplicate comments</li>
560 <li>{{ check "ST1003" }} no longer complains about ALL_CAPS in variable names that don't contain any letters</li>
561 <li>Incorrect position information in various checks have been fixed</li>
562 <li>Crashes in various checks have been fixed</li>
565 <h2 id="2020.2.1">Staticcheck 2020.2.1 release notes</h2>
568 This release eliminates some false negatives as well as false positives, makes the <code>staticcheck</code> command less noisy and fixes a potential security issue.
572 <li>{{ check "SA4020" }} no longer claims that <code>case nil</code> is an unreachable case in a type switch.</li>
573 <li>{{ check "S1025" }} no longer marks uses of Printf as unnecessary when the printed types implement the <code>fmt.Formatter</code> interface.</li>
574 <li>Various checks may now detect bugs in conditional code that were previously missed. This was a regression introduced in Staticcheck 2020.1.</li>
575 <li>The <code>staticcheck</code> command no longer reminds the user of the <code>-explain</code> flag every time problems are found. This was deemed too noisy.</li>
577 We've updated our dependency on <code>golang.org/x/tools</code> to guard against arbitrary code execution on Windows.
578 Note that to be fully safe, you will also have to update your installation of Go.
579 See the <a href="https://blog.golang.org/path-security">Command PATH security in Go</a> article by the Go authors for more information on this potential vulnerability.