Description
What version of Go are you using (go version
)?
$ go version go version go1.15.5 linux/amd64
Does this issue reproduce with the latest release?
Yes, at least with Go 1.15.5.
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/home/ayke/.cache/go-build" GOENV="/home/ayke/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GOMODCACHE="/home/ayke/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/ayke:/home/ayke" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/home/ayke/tmp/constrepro/go.mod" 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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build759953502=/tmp/go-build -gno-record-gcc-switches"
What did you do?
There is no easy way of reproducing this, so I made a new repository with a reproducer in code form: https://github.com/aykevl/constrepro
After cloning it, try running it:
go run . ./const
What did you expect to see?
I expected the following output:
instruction: 5:uint32 / 20:uint32
value: 20:uint32
result: 20 true
You can get this if you use the other twenty
constant in ./const/const.go (see comment).
What did you see instead?
instruction: 5:uint32 / 20:uint32
value: 20:uint32
panic: 20 not an Int
goroutine 1 [running]:
go/constant.Uint64Val(0x7194e0, 0xc000231540, 0xc0001bde60, 0x2)
/usr/local/go/src/go/constant/value.go:484 +0x189
main.main()
/home/ayke/tmp/constrepro/main.go:37 +0x231
exit status 2
Clearly, 20
is an int. But somewhere it seems to have been converted to a float. You can see this if you inspect the generated AST (see line 40):
23 . . . Specs: []ast.Spec (len = 1) {
24 . . . . 0: *ast.ValueSpec {
25 . . . . . Names: []*ast.Ident (len = 1) {
26 . . . . . . 0: *ast.Ident {
27 . . . . . . . NamePos: /home/ayke/tmp/constrepro/const/const.go:6:2
28 . . . . . . . Name: "twenty"
29 . . . . . . . Obj: *ast.Object {
30 . . . . . . . . Kind: const
31 . . . . . . . . Name: "twenty"
32 . . . . . . . . Decl: *(obj @ 24)
33 . . . . . . . . Data: 0
34 . . . . . . . }
35 . . . . . . }
36 . . . . . }
37 . . . . . Values: []ast.Expr (len = 1) {
38 . . . . . . 0: *ast.BasicLit {
39 . . . . . . . ValuePos: /home/ayke/tmp/constrepro/const/const.go:6:11
40 . . . . . . . Kind: FLOAT
41 . . . . . . . Value: "2e1"
42 . . . . . . }
43 . . . . . }
44 . . . . }
45 . . . }
So somehow the value is interpreted as an integer by the SSA package, but in the AST it is somehow considered a float. I think the AST here is wrong (or maybe constant.Uint64Val
), as the code typechecks just fine and is accepted by the Go toolchain.
(This is the bug I was referring to at the bottom of #43163).