go-tools icon indicating copy to clipboard operation
go-tools copied to clipboard

staticcheck: missed deprecated references within struct initializer

Open gburt opened this issue 6 years ago • 3 comments

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!

gburt avatar Sep 29 '19 21:09 gburt

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.

dominikh avatar Sep 30 '19 01:09 dominikh

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.

fho avatar May 04 '22 10:05 fho

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.

joanlopez avatar Jan 04 '24 19:01 joanlopez