Currently, SA4006 only detects unused values if the rhs of the assignment is a function call, but not for other expressions. That is because in the SSA form, those assignments are never represented in the first place.
Example:
func fn1(arg int) {
x := 1
x = 2
x = 3
fmt.Println(x)
}
func fn2(arg int) {
x := gen()
x = gen()
x = gen()
fmt.Println(x)
}
func gen() int { return 0 }
/*
foo.go:13:2: this value of x is never used (SA4006)
foo.go:14:2: this value of x is never used (SA4006)
*/
If this information is removed from the SSA representation, how are you going to retrieve it?
Also we don't seem to be matching post increment/decrement or <binop>= even when they show up in SSA.
How does ineffassign do it?
It probably just looks at the AST differently than we do.
This one is really annoying and bites me all the time. Just recently, on a hobby project of mine, I've spent ~15 minutes pondering, why do I have a panic. The code used to be:
func NewFoo() (f Foo) {
return foo{}
}
(Foo is an interface.) Then foo got some pointer fields, and instead of rewriting it into:
func NewFoo(b *Bar) (f Foo) {
f = foo{bar: b}
// Some stuff.
return f
}
I accidentally miss-rewrote it into:
func NewFoo(b *Bar) (f Foo) {
f = foo{bar: b}
// Some stuff.
return foo{} // N.B. Should be "f" here.
}
I guess ineffassign it is for now聽:-/
@ainar-g I'm working on it.
I had a buggy code with forgotten pointer, that hopefully could be flagged as ineffective assignment.
func foo(r Row /* this should have been a pointer */, postcode region.Postcode) {
if r.Postcode != postcode {
r.Postcode = postcode
}
}
Most helpful comment
I had a buggy code with forgotten pointer, that hopefully could be flagged as ineffective assignment.