Go-tools: False positive on U1000: "unused type" is actually used

Created on 10 Apr 2019  ·  10Comments  ·  Source: dominikh/go-tools

Hi,

Our verify jobs started failing about an hour ago with this error: https://gitlab.com/nick.thomas/gitlab-workhorse/-/jobs/194368582 -> https://gitlab.com/gitlab-org/gitlab-workhorse/issues/217

internal/gitaly/gitaly.go:25:6: type connectionsCache is unused (U1000)

Here's a minimal reproducer:

package foo

type connectionsCache struct {
    foo string
}

var (
    cache = connectionsCache{
        foo: "Foo",
    }
)

func Foo() string {
    return cache.foo
}

And console output:

staticcheck foo.go
foo.go:4:6: type connectionsCache is unused (U1000)

I see https://github.com/dominikh/go-tools/issues/416 was closed just 4 hours ago - perhaps it's a regression caused by that fix?

false-positive

Most helpful comment

I was just about to report this. In case it might be useful, here's a different reproducer (using type aliases):

package main

import "fmt"

type someStringer struct{}

func (someStringer) String() string {
    return "stuff"
}

type firstAlias = someStringer
type secondAlias = someStringer

func main() {
    stringers := []fmt.Stringer{&firstAlias{}, &secondAlias{}}
    for _, c := range stringers {
        fmt.Println(c)
    }
}

output:

u1000repro.go:11:6: type firstAlias is unused (U1000)
u1000repro.go:12:6: type secondAlias is unused (U1000)

All 10 comments

I was just about to report this. In case it might be useful, here's a different reproducer (using type aliases):

package main

import "fmt"

type someStringer struct{}

func (someStringer) String() string {
    return "stuff"
}

type firstAlias = someStringer
type secondAlias = someStringer

func main() {
    stringers := []fmt.Stringer{&firstAlias{}, &secondAlias{}}
    for _, c := range stringers {
        fmt.Println(c)
    }
}

output:

u1000repro.go:11:6: type firstAlias is unused (U1000)
u1000repro.go:12:6: type secondAlias is unused (U1000)

The first issue was fixed by bf9787c127f89e734632306cbd00b834786386ce – the second issue is a separate one I am currently working on.

Thanks for looking into this so quickly @dominikh !

Your new commit fixes my minimal repro above, but looking at the full pipeline, it now fails with something most unexpected: https://gitlab.com/nick.thomas/gitlab-workhorse/-/jobs/194403408

honnef.co/go/tools/unused/unused.go:1272:15: field.Embedded undefined (type *types.Var has no field or method Embedded)

Sorry to be such a pain! I've tried looking at the source, but I'm finding it quite difficult to jump straight into it.

The second issue was fixed by 6da49aace82e94acd4695e7867d968dda0e456a6

@lupine (*go/types.Var).Embedded was added in Go 1.11 – We, much like the rest of the Go ecosystem, support the last two versions of Go. Currently that is 1.11 and 1.12. You seem to be using an older version.

Embedded seems to be a synonym for Anonymous, which has been around since Go 1.5, and we could switch to it. However, one of our crucial dependencies, go/packages, already dropped support for Go 1.10, so you'd be out of luck the moment you update that, anyway.

No problem, thanks for explaining. I was worried it was another regression introduced by the new commit, is all!

The second issue was fixed by 6da49aa

Thanks!

Hi, same here. And yet another reproduction case:

code:

package main

type AA interface {
    A()
}

type BB interface {
    AA
}

type CC interface {
    BB
    C()
}

func c(cc CC) {
    cc.A()
}

type z struct{}

func (z) A() {
    //
}

func (z) B() {
    //
}

func (z) C() {
    //
}

func main() {
    c(z{})
}

output:

$ staticcheck u1000repro.go 
u1000repro.go:7:6: type BB is unused (U1000)

@lootek Fixed in 747de16c19d0445d584b301957201f6060367166

Was this page helpful?
0 / 5 - 0 ratings