staticcheck: missed deprecated references within struct initializer
The deprecation linter has false-negatives when:
- instantiating structs - assignment of deprecated fields is not flagged
- all references to deprecates structs and fields when the struct is in the same pkg as the caller
$ cat example.go:
package main
import (
"example/bar"
"fmt"
)
// Deprecated: do not use
type pkgObj struct {
// Deprecated: Do not use
DepField string
}
func main() {
// all references to deprecated things in the same pkg are FN
obj1 := &pkgObj{ // FN because in same pkg
DepField: "xyz", // FN because in same pkg
}
obj1.DepField = "xyz" // FN because in same pkg
fmt.Printf("field: %v\n", obj1.DepField) // FN because in same pkg
// struct-instantiation references to deprecated fields in other packages are FN:
obj := &bar.Obj{ // TP
DepField: "xyz", // FN b/c struct instantiation
}
obj.DepField = "xyz" // TP
fmt.Printf("field: %v\n", obj.DepField) // TP
}
$ cat bar/obj.go:
package bar
// Obj is a type with a deprecated field
//
// Deprecated: do not use
type Obj struct {
// Foo
//
// Deprecated: Do not use
DepField string
}
Actual output:
$ ~/staticcheck/staticcheck .
example.go:23:10: bar.Obj is deprecated: do not use (SA1019)
example.go:26:2: obj.DepField is deprecated: Do not use (SA1019)
example.go:27:28: obj.DepField is deprecated: Do not use (SA1019)
Expected output:
$ ~/staticcheck/staticcheck .
example.go:16:11: pkgObj is deprecated: do not use (SA1019)
example.go:17:3: pkgObj.DepField is deprecated: do not use (SA1019)
example.go:19:2: pkgObj.DepField is deprecated: do not use (SA1019)
example.go:20:28: pkgObj.DepField is deprecated: do not use (SA1019)
example.go:23:10: bar.Obj is deprecated: do not use (SA1019)
example.go:24:3: obj.DepField is deprecated: Do not use (SA1019)
example.go:26:2: obj.DepField is deprecated: Do not use (SA1019)
example.go:27:28: obj.DepField is deprecated: Do not use (SA1019)
Versions etc:
$ ~/staticcheck/staticcheck -version
staticcheck 2019.2.3
$ go version
go version go1.12.8 linux/amd64
$ ~/staticcheck/staticcheck -debug.version
staticcheck 2019.2.3
Compiled with Go version: go1.13
Main module:
honnef.co/go/[email protected] (sum: h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=)
Dependencies:
github.com/BurntSushi/[email protected] (sum: h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=)
golang.org/x/[email protected] (sum: h1:MQEvx39qSf8vyrx3XRaOe+j1UDIzKwkYOVObRgGPVqI=)
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/gburt/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/gburt/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/home/gburt/tmp/go-build252976518=/tmp/go-build -gno-record-gcc-switches"
Thanks for such a great tool!
instantiating structs - assignment of deprecated fields is not flagged
That seems like a false negative, I'll look into it.
all references to deprecates structs and fields when the struct is in the same pkg as the caller
This is working as intended. Deprecation is intended for exported API that should no longer be used by other packages. A package that has deprecated API can, however, still use that very API to implement the non-deprecated alternatives. Consider this example:
// Deprecated: use SafeOp instead
func UnsafeOp() T
func SafeOp() T {
ret := UnsafeOp()
return makeSafe(ret)
}
Furthermore, there is no notion of deprecating unexported API that would cause intra-package deprecation warnings.
We also encountered the issue that staticcheck does not complain if a deprecated struct field is assigned when the struct is instantiated (in another package). This causes that from now and then new code is introduced that accidentally uses deprecated functionality in our codebase.
What would need to be changed to fix the issue? If it's not too complicated / a lot of effort, I could give it a try.
instantiating structs - assignment of deprecated fields is not flagged
That seems like a false negative, I'll look into it.
https://github.com/dominikh/go-tools/pull/1382 seems to fix it, so I think it worths a look! @dominikh Now, for instance this acknowledged deprecation is not being detected, and the same for many other ones similar.