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

go/constant: passing nil to BinaryOp or Compare panics with unreachable #17812

Closed
dominikh opened this issue Nov 5, 2016 · 7 comments
Closed

Comments

@dominikh
Copy link
Member

dominikh commented Nov 5, 2016

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

go version go1.7.3 linux/amd64

What did you do?

https://play.golang.org/p/G0V0HApS-t

What did you expect to see?

true

What did you see instead?

panic: unreachable

goroutine 1 [running]:
panic(0x122680, 0x1050a130)
	/usr/local/go/src/runtime/panic.go:500 +0x720
go/constant.ord(0x0, 0x0, 0x0, 0x0)
	/usr/local/go/src/go/constant/value.go:865 +0xa0
go/constant.match(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/go/src/go/constant/value.go:875 +0xc0
go/constant.Compare(0x0, 0x0, 0x27, 0x0, 0x0, 0x200, 0x0, 0x3274)
	/usr/local/go/src/go/constant/value.go:1179 +0x80
main.main()
	/tmp/sandbox842734224/main.go:10 +0x40

I don't know if an untyped nil is a valid constant.Value – I obtained it from a *ssa.Const.Value from the following typechecked package, the BinOp specifically:

package foo

func foo() {
	_ = (interface{})(nil) == (interface{})(nil)
}

which compiles to

func foo():
0:                                                                entry P:0 S:0
	t0 = nil:interface{} == nil:interface{}                            bool
	return

If nil is valid, no panic should occur. If nil is not valid, it should have a more descriptive panic, and go/ssa might have a bug of its own.

/cc @alandonovan @griesemer

@griesemer
Copy link
Contributor

nil is not a valid go/constant Value. In general, we don't describe in every package that nil is not valid - we usually describe when nil is valid. We also don't test every single impossible value (see https://play.golang.org/p/O62KzUF86T for instance). The documentation says "The comparison must be defined for the operands." - admittedly vague but it's clear to expect the unexpected otherwise.

@dominikh
Copy link
Member Author

dominikh commented Nov 6, 2016

@griesemer Should I file a bug for go/ssa instead, or is it also expected that an *ssa.Const.Value can be nil?

@griesemer
Copy link
Contributor

In retrospect I agree that the error message is wrong: That code clearly is reachable after all, even if it means incorrect input. I will fix that.

And yes, if go/ssa produces a nil constant Value it probably should say that either nil is possible and means "no constant value", or there's a bug (documentation or otherwise).

@griesemer griesemer reopened this Nov 6, 2016
@griesemer griesemer self-assigned this Nov 6, 2016
@dominikh
Copy link
Member Author

dominikh commented Nov 6, 2016

I.e. is https://play.golang.org/p/ONBGaMJD1d valid and expected to disagree with go/constant's definition of a valid Value?

@griesemer griesemer added this to the Go1.8Maybe milestone Nov 6, 2016
@alandonovan
Copy link
Contributor

The ssa and go/constant packages are both working as intended.

The constant package does not allow nil operands to its functions. (When a Go function accepts optional arguments or nil, this is usually explicitly documented and in the absence of documentation it should be assumed unsafe.)

The ssa package uses a nil constant.Value to indicate a typed nil value, even though nil is not a constant according to the language spec. See https://godoc.org/golang.org/x/tools/go/ssa#Const:

[...] a Const may represent the nil value of any reference type---interface, map, channel, pointer, slice, or function---but not "untyped nil". [...] Value holds the exact value of the constant, independent of its Type(), using the same representation as package go/exact uses for constants, or nil for a typed nil value.

As a result, you must check the ssa.Const.Value field is non-nil before passing it to a function such as constant.Compare.

@gopherbot
Copy link

CL https://golang.org/cl/32870 mentions this issue.

@gopherbot
Copy link

CL https://golang.org/cl/32872 mentions this issue.

gopherbot pushed a commit that referenced this issue Nov 7, 2016
For #17812.

Change-Id: I58411aaa0e8b2250a16ddb20c951e39da3d601e8
Reviewed-on: https://go-review.googlesource.com/32872
Reviewed-by: Alan Donovan <adonovan@google.com>
@golang golang locked and limited conversation to collaborators Nov 7, 2017
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

4 participants