shift_const_width.mx raw

   1  // A shift's result type follows the left operand, not the count. Where the
   2  // left operand is an untyped constant too wide for the count's type, adopting
   3  // the count's type truncated it: `0x20000000000000 >> uint32(k)` computed 0
   4  // where Go computes 2^49. math.expm1 relies on this expression, so the whole
   5  // function returned 0 for the affected branch.
   6  package main
   7  
   8  func shifted(k uint32) (r uint64) {
   9  	return uint64(0x20000000000000 >> k)
  10  }
  11  
  12  func combined(k uint32) (r uint64) {
  13  	return uint64(0x3ff0000000000000 - (0x20000000000000 >> k))
  14  }
  15  
  16  func main() {
  17  	if shifted(0) != 9007199254740992 {
  18  		panic("shift truncated the left operand")
  19  	}
  20  	if shifted(10) != 9007199254740992>>10 {
  21  		panic("shift by 10 truncated the left operand")
  22  	}
  23  	if combined(0) != 4598175219545276416 {
  24  		panic("subtraction over the shift was wrong")
  25  	}
  26  	if combined(20) != 4607182410210082816 {
  27  		panic("subtraction over the shift was wrong at 20")
  28  	}
  29  	println(combined(0))
  30  }
  31