0

Why the following code works without overflow bug?: (overflow bug with uint64 type, if overflow happens in function)

package main


func foo(i uint64) int{

    return (1 << i)
}

func main() {

    foo(99)

}

A simple bar := 1 << 99 would cause a bug. if you put bar := 1 << 99 you get prog.go:11:9: constant 633825300114114700748351602688 overflows int.

And bar := 1 << 512 gives prog.go:11:11: shift count too large: 512

https://play.golang.org/p/0iiUlCiYTDR

dibbidabbi
  • 41
  • 1
  • 4
  • 3
    The go [spec](https://golang.org/ref/spec#Integer_operators) says `There is no upper limit on the shift count` -- why do you expect an error? – JimB Feb 22 '18 at 18:36
  • 1
    Another relevant quote from the spec: `For signed integers, the operations +, -, *, /, and << may legally overflow and the resulting value exists and is deterministically defined by the signed integer representation, the operation, and its operands.` – squiguy Feb 22 '18 at 18:37
  • we have unsigned integers here – dibbidabbi Feb 22 '18 at 18:39
  • And what exactly is meant here by "overflow bug"? – Adrian Feb 22 '18 at 18:41
  • if you put `bar := 1 << 99` you get `prog.go:11:9: constant 633825300114114700748351602688 overflows int` – dibbidabbi Feb 22 '18 at 18:45
  • and `bar := 1 << 512` gives `prog.go:11:11: shift count too large: 512` – dibbidabbi Feb 22 '18 at 18:46
  • 1
    @dibbidabbi For that see [Does go compiler's evaluation differ for constant expression and other expression](https://stackoverflow.com/questions/39444852/does-go-compilers-evaluation-differ-for-constant-expression-and-other-expressio/39445372#39445372). – icza Feb 22 '18 at 19:00
  • Inside the fonction it’s unsigned, but on your simple bar := 1 << 99 example, it’s not. – mgagnon Feb 22 '18 at 19:00

1 Answers1

1

According to the "Integer Operations" section of the language spec:

There is no upper limit on the shift count.

So the behavior you see is intended.

Note that if you are using constants for both of the operands then the compiler will try to replace the statement with a constant, which may overflow your defined type:

x := uint64(1) << 500
// ERROR: constant ... overflows uint64

However, you can shift any integer by any value, any number of times:

x, y := uint64(1), uint64(0xffffffff)
for {
  x <<= y
}
// OK: x definitely has no bits set 
maerics
  • 151,642
  • 46
  • 269
  • 291
  • there is an upper limit of 511 – dibbidabbi Feb 22 '18 at 18:41
  • @dibbidabbi if you're using a constant shift value then the compiler will attempt to replace the statement with a constant, whose resulting value _may_ overflow the type you've defined. However, you can still shift any number of times, with any value in `[0,maxUint64]`. – maerics Feb 22 '18 at 18:51
  • sounds better, thanks. the compiler should be more consistent. – dibbidabbi Feb 22 '18 at 18:56