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: inconsistent type check for the % operator #50600

Closed
hajimehoshi opened this issue Jan 13, 2022 · 4 comments
Closed

cmd/compile: inconsistent type check for the % operator #50600

hajimehoshi opened this issue Jan 13, 2022 · 4 comments

Comments

@hajimehoshi
Copy link
Member

@hajimehoshi hajimehoshi commented Jan 13, 2022

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

$ go version
go version go1.17.4 darwin/amd64

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/hajimehoshi/Library/Caches/go-build"
GOENV="/Users/hajimehoshi/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/hajimehoshi/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/hajimehoshi/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.17.4"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/60/khbk2xqn1c5bml1byjn89dwc0000gn/T/go-build1966691589=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Compile this: https://go.dev/play/p/Iit1KG_OA8Z

package main

import "fmt"

func main() {
	const a = int(1) % 2.0
	fmt.Println(a)
	const b = 1 % 2.0
	fmt.Println(b)
}

What did you expect to see?

No error: 1 and 1 are printed

What did you see instead?

Compile error:

./prog.go:10:14: invalid operation: 1 % 2 (operator % not defined on untyped float)

Go build failed.
@hajimehoshi
Copy link
Member Author

@hajimehoshi hajimehoshi commented Jan 13, 2022

<< worked as expected:

https://go.dev/play/p/VL3fooh-F1z

package main

import "fmt"

func main() {
	const a = int(1) << 2.0
	fmt.Println(a)
	const b = 1 << 2.0
	fmt.Println(b)
}

@ALTree
Copy link
Member

@ALTree ALTree commented Jan 13, 2022

For constant expressions, << is a little different from the other operators:

If the left operand of a constant shift expression is an untyped constant, the result is an integer constant;

So the result of const b = 1 << 2.0 is an integer constant, which means that 1 is considered an (promoted to?) integer. On the other hand:

If the untyped operands of a binary operation (other than a shift) are of different kinds, the result is of the operand's kind that appears later in this list: integer, rune, floating-point, complex.

So the result of const b = 1 % 2.0 is of kind floating point, which means that 1 is treated as a constant of floating-point kind, and then you get the error about % not being defined on floats.

@hajimehoshi
Copy link
Member Author

@hajimehoshi hajimehoshi commented Jan 13, 2022

Thank you for elaboration. I understand the current behavior is correct from the specification.

I was wondering why the shift operators are special, but this issue is not a bug anyway. Let me close this.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jan 14, 2022

There was a lot of discussion and fiddling with the types of the shift operators in the early days of Go, and they are still complicated. The shift operators are the only operators that don't use the same type on both the left and right hand sides. Go requires a way to set the type of an untyped constant. What is right way to determine the type of an untyped constant shifted by a non-constant value? What the language finally decided was our best answer to that question.

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

No branches or pull requests

3 participants