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

proposal: cmd/compile: provide 'evaluated but not used' error when function returned from another function is not used (called or assigned) #29428

Closed
HaraldNordgren opened this issue Dec 26, 2018 · 5 comments

Comments

@HaraldNordgren
Copy link
Member

What version of Go are you using (go version)?

$ go version
go version go1.11.1 darwin/amd64

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/harald/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/harald/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.11.1/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.11.1/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/w3/11rv94110qnc2l400nlz7gmc0000gn/T/go-build739722607=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

https://play.golang.org/p/NjLj1WrbUuF

@HaraldNordgren
Copy link
Member Author

This bit me in the butt recently when writing code like this:

func defaultErrorHandler(p *httputil.ReverseProxy) func(rw http.ResponseWriter, req *http.Request, err error) {
	return func(rw http.ResponseWriter, req *http.Request, err error) {
		rw.WriteHeader(http.StatusBadGateway)
	}
}

func CustomizedErrorHandlerOption(p *httputil.ReverseProxy) {
	p.ErrorHandler = func(rw http.ResponseWriter, req *http.Request, err error) {
		if someConditionFulfilled(err) {
			rw.WriteHeader(http.StatusBadRequest)
			return
		}

		// Should have been 'defaultErrorHandler(p)(rw, req, err)'
		defaultErrorHandler(p)
	}
}

The call defaultErrorHandler(p) returned a function that was then never evaluated. But the compiler doesn't warn, and the underlying logic is not executed.

@odeke-em
Copy link
Member

odeke-em commented Dec 27, 2018

Hello @HaraldNordgren, thank you for filing this issue and welcome to the Go project!

The goal of the compiler's "mark-used" pass is to find and report unused variables/expressions to check the validity of the Go program -- if all the expressions are evaluated and used, that makes for a correct Go program. Any other extra passes would perhaps become too intrusive and less expressive, which would open up the flood gates and make complicated cases. For example you might want to invoke f1 just for the side effect but without using its runtime return value. What happens when we return a closure that's dynamically created? What happens if the return signature has more than a function e.g. func foo() (int, func())?

Also the Go compiler doesn't emit warnings. In addition, this would also mean that we'd break the Go1 compatibility whereby programs that compiled before this change(if it were accepted) would be broken.

Perhaps this could be a special case for go vet but even that I think might be complex.

I'll page some experts for some more ideas @griesemer @josharian @ianlancetaylor

@odeke-em odeke-em changed the title Give 'evaluated but not used' error when function returned from another function is not called proposal: cmd/compile: provide 'evaluated but not used' error when function returned from another function is not called Dec 27, 2018
@gopherbot gopherbot added this to the Proposal milestone Dec 27, 2018
@griesemer griesemer changed the title proposal: cmd/compile: provide 'evaluated but not used' error when function returned from another function is not called proposal: cmd/compile: provide 'evaluated but not used' error when function returned from another function is not used (called or assigned) Dec 27, 2018
@griesemer
Copy link
Contributor

This is an interesting, if rare, special case. Reporting an error in this case might prevent coding errors that are easily missed. But I'm not sure how intrusive it would be and whether it would meet the usual vet criteria. An experiment (implement the vet check and apply it) might be necessary to make an educated decision.

@randall77
Copy link
Contributor

I have seen a similar error a bunch of times inside Google:

   var err error = ...
   fmt.Printf("failed: %s\n", err.Error)

It's printing a closure pointer, not the error text. It should be:

   var err error = ...
   fmt.Printf("failed: %s\n", err.Error())

(Just err would also work.)

In this case, it isn't a function returning a function that isn't called, but a method expression that's never called. The extra challenge here is deciding whether the method is called inside fmt.Printf.

@rsc
Copy link
Contributor

rsc commented Jan 9, 2019

The compiler can't make this an error - that would violate the language spec.
But vet could warn about something like this if it were essentially always an error.

And in fact vet should already be warning about @randall77's example.
(It does: https://play.golang.org/p/oDdHnjwc1Ey)

The defaultErrorHandler(p) is less clearly erroneous. We call functions and ignore their results all the time. Maybe that returned a cleanup function that is unnecessary in this context. I'm not sure there's much we can do to fix your particular problem.

If you want to try making vet more aggressive as an experiment and come back with a more precise extra condition to check, that's fine, but probably it is not good enough. See cmd/vet/README for criteria. Feel free to file a new issue if you do find a clearer criteria.

@rsc rsc closed this as completed Jan 9, 2019
@golang golang locked and limited conversation to collaborators Jan 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants