New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: diagnose unused variable even in closure #3059

Open
rogpeppe opened this Issue Feb 17, 2012 · 19 comments

Comments

Projects
None yet
@rogpeppe
Contributor

rogpeppe commented Feb 17, 2012

package main

func main() {
    i := 0
    go func() {
        i = 1
    }()
}

This compiles without errors.
I would expect this to give an "i declared and not used" error.
@rsc

This comment has been minimized.

Contributor

rsc commented Feb 17, 2012

Comment 1:

Labels changed: added priority-later, removed priority-triage.

Owner changed to builder@golang.org.

Status changed to Accepted.

@rsc

This comment has been minimized.

Contributor

rsc commented Sep 12, 2012

Comment 2:

Labels changed: added go1.1maybe.

@rsc

This comment has been minimized.

Contributor

rsc commented Mar 12, 2013

Comment 3:

[The time for maybe has passed.]

Labels changed: removed go1.1maybe.

@rsc

This comment has been minimized.

Contributor

rsc commented Jul 30, 2013

Comment 4:

Labels changed: added go1.2maybe.

@rsc

This comment has been minimized.

Contributor

rsc commented Jul 30, 2013

Comment 5:

Labels changed: added feature.

@robpike

This comment has been minimized.

Contributor

robpike commented Aug 16, 2013

Comment 6:

Not likely to happen in 1.2.

Labels changed: added go1.3maybe, removed go1.2maybe.

@robpike

This comment has been minimized.

Contributor

robpike commented Aug 20, 2013

Comment 7:

Labels changed: removed go1.3maybe.

@remyoudompheng

This comment has been minimized.

Contributor

remyoudompheng commented Sep 29, 2013

Comment 8:

Issue #6414 has been merged into this issue.

@rsc

This comment has been minimized.

Contributor

rsc commented Nov 27, 2013

Comment 9:

Labels changed: added go1.3maybe.

@rsc

This comment has been minimized.

Contributor

rsc commented Nov 27, 2013

Comment 10:

Labels changed: removed feature.

@rsc

This comment has been minimized.

Contributor

rsc commented Dec 4, 2013

Comment 11:

Labels changed: added release-none, removed go1.3maybe.

@rsc

This comment has been minimized.

Contributor

rsc commented Dec 4, 2013

Comment 12:

Labels changed: added repo-main.

@zeebo

This comment has been minimized.

Contributor

zeebo commented Dec 19, 2014

I ran into this problem today when code that was compiling fine under cmd/gc was rejected during godoc's pointer analysis by go/types. It would be nice to have this fixed so that I didn't have to worry and find all the spots we do this in our code base and keep track of if it's happening during code review.

@rsc rsc added this to the Unplanned milestone Apr 10, 2015

@rsc rsc changed the title from cmd/gc: diagnose unused variable even in closure to cmd/compile: diagnose unused variable even in closure Jun 8, 2015

mwhudson added a commit to mwhudson/juju that referenced this issue Dec 14, 2015

fix api/metricsadder & apiserver/environment test compilation with ne…
…w gccgo

gccgo (in xenial at least) is stricter than gc when it comes to a certain
class of declared but not used variable, see:

    golang/go#6415
    golang/go#3059

jujubot added a commit to juju/juju that referenced this issue Dec 15, 2015

Merge pull request #3961 from mwhudson/metricsadder-vars
fix api/metricsadder & apiserver/environment test compilation with ne…

…w gccgo

gccgo (in xenial at least) is stricter than gc when it comes to a certain
class of declared but not used variable, see:

    golang/go#6415
    golang/go#3059

davecheney added a commit to pkg/errors that referenced this issue Feb 27, 2017

Move benchmark assigned err to global exported variable (#106)
toperr is not used, but the go compiler itself doesn't detect this
because it's within an anonymous function. However, go/types does
detect this as being unused, which causes any static analysis tools
which uses go/types' type checker to fail with the message "toperr
assigned and not used".

The final result of the benchmarked function is instead assigned to
an exported global variable to ensure the compiler cannot now, nor
in the future optimise away the function calls due to no observable
side effects.

It was chosen to assign the final result, after the benchmark loop,
to the global variable, as this best follows the example set in the
CL https://go-review.googlesource.com/#/c/37195/. As opposed to
having each call to f assign to the global. This also appears to
better align with the original author's intention of toperr.

This change had no observable impact on the benchmark.

Related golang/go#3059.
Related golang/go#8560.

Thanks dominikh for additional clarifications.

rudle pushed a commit to rudle/gosnmp that referenced this issue Mar 3, 2017

Sean Sorrell
Remove unused err
The declaration `var err` is unused and it causes some static analysis tools (go
guru) to throw an error on this repository. I'm not sure what ought to be done
here, but consider this a start.

In fact, this ought to be a compile time error. See this issue for the go
runtime golang/go#3059

@rudle rudle referenced this issue Mar 3, 2017

Merged

Remove unused err #40

@bradfitz bradfitz modified the milestones: Go1.9Early, Go1.10Early May 3, 2017

@bradfitz bradfitz modified the milestones: Go1.10Early, Go1.10 Jun 14, 2017

@mdempsky mdempsky modified the milestones: Go1.10, Go1.11 Nov 29, 2017

@gopherbot

This comment has been minimized.

gopherbot commented Mar 21, 2018

Change https://golang.org/cl/101815 mentions this issue: cmd/trace: remove unused variable in tests

gopherbot pushed a commit that referenced this issue Mar 21, 2018

cmd/trace: remove unused variable in tests
Unused variables in closures are currently not diagnosed by the
compiler (this is Issue #3059), while go/types catches them.

One unused variable in the cmd/trace tests is causing the go/types
test that typechecks the whole standard library to fail:

  FAIL: TestStdlib (8.05s)
    stdlib_test.go:223: cmd/trace/annotations_test.go:241:6: gcTime
    declared but not used
  FAIL

Remove it.

Updates #24464

Change-Id: I0f1b9db6ae1f0130616ee649bdbfdc91e38d2184
Reviewed-on: https://go-review.googlesource.com/101815
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>

@bradfitz bradfitz modified the milestones: Go1.11, Go1.12 May 18, 2018

@gopherbot gopherbot modified the milestones: Go1.12, Unplanned May 23, 2018

@gopherbot

This comment has been minimized.

gopherbot commented Jun 28, 2018

Change https://golang.org/cl/121455 mentions this issue: doc: document new vet behaviour for typechecking failures

gopherbot pushed a commit that referenced this issue Jul 17, 2018

doc/go1.11: explain new vet typechecking behaviour in release notes
Since Go1.10, go test runs vet on the tests before executing them.

Moreover, the vet tool typechecks the package under analysis with
go/types before running. In Go1.10, a typechecking failure just caused
a warning to be printed. In Go1.11, a typechecking failure will cause
vet to exit with a fatal error (see Issue #21287).

This means that starting with Go1.11, tests that don't typecheck will
fail immediately. This would not normally be an issue, since a test
that doesn't typecheck shouldn't even compile, and it should already
be broken.

Unfortunately, there's a bug in gc that makes it accept programs with
unused variables inside a closure (Issue #3059). This means that a
test with an unused variable inside a closure, that compiled and
passed in Go1.10, will fail in the typechecking step of vet starting
with Go1.11.

Explain this in the 1.11 release notes.

Fixes #26109

Change-Id: I970c1033ab6bc985d8c64bd24f56e854af155f96
Reviewed-on: https://go-review.googlesource.com/121455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
@odeke-em

This comment has been minimized.

Member

odeke-em commented Oct 28, 2018

Without having fully dug into this I am hypothesizing this might just be a consequence of us taking the address of higher scope variables to make a pointer then technically "assigned" to it
so it perhaps became the equivalent of

var i int
*(&i) = 1

thus when used in the closure got rewritten as

var i int
go func(i *int) {
    *i = 1
}()

which if true would then mean that a fix for this would involve specially marking as used scoped-by-manually-address-of'd variables that were previously just values in their original scope
so in pseudo code

in closure or inner scope, for &prefixedVariables from an outer scope {
    on assignment, markAsUsed iff:
        Originally a pointer in outer scope
}

Kindly paging @griesemer @randall77 @mdempsky for discussion and perhaps to help me check my hypothesis and then I can mail out a fix if plausible.

@randall77

This comment has been minimized.

Contributor

randall77 commented Oct 29, 2018

Yes, we're effectively doing &i when building the closure, which defeats the unused variable analysis.
I'm not sure what the fix would be. We'd need to keep track of, for every variable whose address is taken, whether that address was used in a read or a write (or unknown). It sounds tricky.

@griesemer

This comment has been minimized.

Contributor

griesemer commented Oct 29, 2018

It needs to be done independently of (the implementation detail) whether an address was taken. go/types does this right, but it also does it earlier, during type-checking.

Not urgent.

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Oct 29, 2018

It's not urgent, but it is an ongoing pain point, because different compilers behave differently. That causes people to write code that works with one compiler and complain when it fails with a different one. So it really ought to be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment