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/go: compiler does not report error on mismatched integer types #37518

Closed
mer041352 opened this issue Feb 27, 2020 · 9 comments
Closed

cmd/go: compiler does not report error on mismatched integer types #37518

mer041352 opened this issue Feb 27, 2020 · 9 comments
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@mer041352
Copy link

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

$ go version
go1.13.7 linux/amd64

Does this issue reproduce with the latest release?

The following code will silently fail to make the correct decision:
var isFound bool
var value int64 = 1
if value == 1 {
isFound = true
} else {
isFound = false
}

This will always evaluate to false unless the code is modified to:
if value == int64(1) {
isFound = true
} else {
isFound = false
}

This should be flagged as an error since the integer types do not match.

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/martin.rothberg/.cache/go-build"
GOENV="/home/martin.rothberg/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/martin.rothberg/gprojects/Joker:/home/martin.rothberg/go/"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/martin.rothberg/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/martin.rothberg/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build874156137=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I added a cast to an int64 to fix the problem.

What did you expect to see?

I expected the compiler to give an error due to the mismatch of the integer types.

What did you see instead?

The program compiled without error and ran, but never saw the literal of 1 as a match for the value of type int64.

@randall77
Copy link
Contributor

I don't understand the bug you're seeing. Can you provide a full program?
This program prints true twice:

package main

func main() {
	println(test1())
	println(test2())
}

func test1() bool {
	var isFound bool
	var value int64 = 1
	if value == 1 {
		isFound = true
	} else {
		isFound = false
	}
	return isFound
}
func test2() bool {
	var isFound bool
	var value int64 = 1
	if value == int64(1) {
		isFound = true
	} else {
		isFound = false
	}
	return isFound
}

You might also want to read about untyped constants. value == 1 is allowed by the language spec because 1 is an untyped constant and is allowed to be used in comparisons with any numeric type.

@ALTree ALTree changed the title go version go1.13.7 linux/amd64 does not report error on mismatched integer types cmd/go: compiler does not report error on mismatched integer types Feb 28, 2020
@ALTree ALTree added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Feb 28, 2020
@mer041352
Copy link
Author

mer041352 commented Feb 28, 2020

I added in interface to my simple code. Now it fails. If I run the example I sent originally, it works.

`package main

import (
"fmt"
)

type junk interface {
getkey() string
getvalue() int64
}

type stuff struct{}

func (s stuff) getkey() string {
return "housekey"
}

func (s stuff) getvalue() int64 {
return 1
}

type stuffFactory func() junk

func createStuff() junk {
return stuff{}
}

type item struct {
key string
value int64
}

func (i item) getkey() string {
return i.key
}

func (i item) getvalue() interface{} {
return i.value
}

func main() {
myitem := item{key:"Gettysburg", value: 1}

value := myitem.getvalue()

fmt.Printf("value = %v\n", value)
fmt.Println("test if statement with int64 and literal")
fmt.Printf("value is of type %T, 1 is of type %T\n", value, 1)

if value == 1 {
    fmt.Println("value is true")
} else {
    fmt.Println("value is false")
}

}`

Running this program gives this output:

bash-4.2$ go run main.go
value = 1
test if statement with int64 and literal
value is of type int64, 1 is of type int
value is false

@ianlancetaylor
Copy link
Contributor

I don't see a bug here, so closing. You may want to take a look at https://blog.golang.org/constants.

@mer041352
Copy link
Author

mer041352 commented Feb 28, 2020 via email

@mer041352
Copy link
Author

mer041352 commented Feb 28, 2020 via email

@randall77
Copy link
Contributor

randall77 commented Feb 28, 2020

var x, y int64
var i, j interface{}
a := x == y
b := i == j
c := i == x

The first comparison compares the values of the variables x and y, as expected.
The second comparison compares both the types and the values of i and j. Both the type and the value have to match, for the equality to be true.
The third comparison is really this: i == (interface{})(x). That is, the concrete type is promoted to an interface before the equality check. Thus, the third comparison compares both the types and values. In this case, the type of x is int64, so an int64 must be in i for the equality to be true.

When you do

var x interface{} = int64(1)
a := x == 1

That 1 on the RHS must be converted to an interface before the equality check is done. Because 1 is a Go constant, it gets the default type for integer constants, which is int. Then when the comparison happens, it returns false because the types don't match (int64 and int are not the same type).

@mer041352
Copy link
Author

mer041352 commented Feb 29, 2020 via email

@mer041352
Copy link
Author

Shouldn't the compiler at least flag this as a type mismatch?

@ianlancetaylor
Copy link
Contributor

I'm not sure what you think the compiler should do. There are several different test cases in this issue. Can you provide a specific example where you think the compiler should behave differently?

@golang golang locked and limited conversation to collaborators Mar 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

5 participants