Skip to content
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 · 24 comments
Open

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

rogpeppe opened this issue Feb 17, 2012 · 24 comments
Assignees
Milestone

Comments

@rogpeppe
Copy link
Contributor

@rogpeppe 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
Copy link
Contributor

@rsc 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
Copy link
Contributor

@rsc rsc commented Sep 12, 2012

Comment 2:

Labels changed: added go1.1maybe.

@rsc
Copy link
Contributor

@rsc rsc commented Mar 12, 2013

Comment 3:

[The time for maybe has passed.]

Labels changed: removed go1.1maybe.

@rsc
Copy link
Contributor

@rsc rsc commented Jul 30, 2013

Comment 4:

Labels changed: added go1.2maybe.

@rsc
Copy link
Contributor

@rsc rsc commented Jul 30, 2013

Comment 5:

Labels changed: added feature.

@robpike
Copy link
Contributor

@robpike robpike commented Aug 16, 2013

Comment 6:

Not likely to happen in 1.2.

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

@robpike
Copy link
Contributor

@robpike robpike commented Aug 20, 2013

Comment 7:

Labels changed: removed go1.3maybe.

@remyoudompheng
Copy link
Contributor

@remyoudompheng remyoudompheng commented Sep 29, 2013

Comment 8:

Issue #6414 has been merged into this issue.

@rsc
Copy link
Contributor

@rsc rsc commented Nov 27, 2013

Comment 9:

Labels changed: added go1.3maybe.

@rsc
Copy link
Contributor

@rsc rsc commented Nov 27, 2013

Comment 10:

Labels changed: removed feature.

@rsc
Copy link
Contributor

@rsc rsc commented Dec 4, 2013

Comment 11:

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

@rsc
Copy link
Contributor

@rsc rsc commented Dec 4, 2013

Comment 12:

Labels changed: added repo-main.

@zeebo
Copy link
Contributor

@zeebo 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 cmd/gc: diagnose unused variable even in closure 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
…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
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
@bradfitz bradfitz modified the milestones: Go1.10Early, Go1.9Early 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
Copy link

@gopherbot 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
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
Copy link

@gopherbot 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
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
Copy link
Member

@odeke-em 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
Copy link
Contributor

@randall77 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
Copy link
Contributor

@griesemer 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
Copy link
Contributor

@ianlancetaylor 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.

@sigxcpu76
Copy link

@sigxcpu76 sigxcpu76 commented Jun 16, 2020

vet detects this but compiler is happy. internal_response is never used.

func (s *AnaServer) VisualizationEvent(ctx context.Context, in *pb.VisualizationEventReq) (*pb.VisualizationEventRes, error) {
...
	internal_response := &ana.VisualizationEventRes{}

...
	if err := customcopier.CopyRecommendedDashPageReq(request.DashPage, in.GetDashPage()); err != nil {
		return nil, err
	}

	if err := s.AnaRpc(func(client ana.GateClient) error {
		internal_response, err = client.VisualizationEvent(ctx, request)
		return err
	}); err != nil {
		return nil, err
	}

	return &pb.VisualizationEventRes{}, nil
}
@mdempsky mdempsky self-assigned this Jun 16, 2020
@gopherbot
Copy link

@gopherbot gopherbot commented Jun 17, 2020

Change https://golang.org/cl/238317 mentions this issue: cmd/compile: recognize unused variables even when captured

@gopherbot
Copy link

@gopherbot gopherbot commented Jun 17, 2020

Change https://golang.org/cl/238538 mentions this issue: cmd/compile: maintain legacy "declared but not used" behavior

@gopherbot
Copy link

@gopherbot gopherbot commented Jun 17, 2020

Change https://golang.org/cl/238537 mentions this issue: cmd/compile: refactor "declared but not used" diagnostic

@mdempsky
Copy link
Member

@mdempsky mdempsky commented Jun 18, 2020

I have CLs uploaded to fix this for Go 1.16 (CL 238537, CL 238317).

@ianlancetaylor points out this might break programs that currently build, and so maybe we should only apply impose the new, stricter behavior when -lang=go1.16 is used (e.g., go 1.16 in a go.mod file). I've prepared CL 238538 to implement this conditional behavior.

gccgo, go/types, and cmd/vet all diagnose the original test case as an error. I'm hopeful that we can avoid introducing conditional behavior in cmd/compile. But if we need to make it conditional, I think that's reasonable.

Relatedly, if all major Go compilers/type-checkers now require all declared variables to be used, we should consider changing the "implementation restriction" into a plain restriction (like how directly imported packages have to be used).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.