-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/compile: inconsistent shift operator type check #66071
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
Comments
https://go.dev/play/p/OHnUA3weL8w might be a more minimized case: package main
import "fmt"
func main() {
a := 1
b := 1.0<<a + 0 // Error
c := 1.0<<a + int(0) // Not error
fmt.Println(b, c)
} |
The spec says:
So this seems an expected behavior. However, I feel like this caused counter-intuitive behaviors. Another example is: package main
import "fmt"
func main() {
s := 1
a := int(1 << s)
b := float32(1 << s) // Fail
fmt.Println(a, b)
} |
Yes, it is not a bug. There is indeed some counter-intuitive sometimes: package main
const s = "Go101.org" // len(s) == 9
var a byte = 1 << len(s) / 128 // len(s) is a constant
var b byte = 1 << len(s[:]) / 128 // s[:] is not a constant, so not len(s[;]) too.
func main() {
println(a, b) // 4 0
} The reason for the design is to make the evaluation of var n = 32
var y = int64(1 << n) |
Hmm, but this varies between 32bits and 64bits. I was wondering why a shift operator is treated in a special way. var n = 0x40000000
var y = int64(4 * n) |
R u sure? |
Yes, I am sure. On Windows:
|
R u sure the '0' is the output of |
Yes.
|
So, usually a binary operator determines an untyped value's type if the other is a typed value. However, a shift operator behaves in a very special way ignoring the right side value's type and using other contexts. |
This is how the language works, it is documented in the spec, and we aren't going to change it now. There have been extensive discussions of this issue in the past on golang-nuts and in issues like #14844. |
If you are sure Windows 32-bit prints 0, then it might be a bug in my opinion.
Only when the right side is not a constant. |
Thanks, but I was wondering if it is possible to change the spec to allow
I don't think this is a bug.
Ah yes, true |
If it is not bug, then the special rule for bit-shift operation is meaningless. |
Are you sure the special rule was introduced for the |
Yes. By the spec, |
I mean I was wondering if you saw the discussion or the background how the spec for shifts was determined. |
Yes, I saw it in a discussion, but it is hard to find it now. If I remember correctly, @ianlancetaylor made the explanation. |
@hajimehoshi The rules for shifts are indeed tricky. They were developed over many years as we encountered different issues in real code. We aren't going to change them now. The basic issue is that constants in Go are untyped, but non-constant expressions have to have a type. Let's say we have an operation with an untyped constant on the left and a typed expression on the right. For most binary operators we simply say that the left hand side is converted to the type of the right hand side. For shifts that does not make sense: there is no necessary connection between the types of the left hand and right hand side. So for shifts we ignore the type of the right hand side and apply the general rule for a plain untyped constant: it gets its type from the context in which it appears. For If we change that, what would we change it to? Experience tells us that the issue will pop up somewhere else. So we've settled the semantics, and we aren't going to change it now. Fortunately shifts of an untyped constant written as |
Thank you for elaborating!
Thanks. This explanation makes the most sense to me. (My understanding is that there are no 'type' relashipships between
I admit this case ( package main
import "fmt"
func main() {
a := 1
b := float32(1 << a)
fmt.Println(b)
} |
Go version
go version go1.22.0 darwin/arm64
Output of
go env
in your module/workspace:What did you do?
Run this:
What did you see happen?
What did you expect to see?
Both are errors, or both are correct. (I hope both are correct). Actually this program worked:
The text was updated successfully, but these errors were encountered: