It is not a bug. The spec says <https://golang.org/ref/spec#Constant_expressions>:
If the left operand of a *constant *shift expression is an untyped > constant, the result is an integer constant; otherwise it is a constant of > the same type as the left operand, which must be of integer type. Any other operation on untyped constants results in an untyped constant of > the same kind (emphasis mine). Given that a is not a constant, 1<<a is not a constant shift expression. Therefore, it's "any other operation" and is given a type from context. The way this happens is described in Operators <https://golang.org/ref/spec#Operators>: The right operand in a shift expression must have integer type or be an > untyped constant representable by a value of type uint. If the left operand > of a non-constant shift expression is an untyped constant, it is first > implicitly converted to the type it would assume if the shift expression > were replaced by its left operand alone. Therefore, the untyped constant 1 in float64(1<<a) is given the type it would assume in float64(1). I don't think it is surprising, that that type is float64. Though arguably, there is a difference between "float64(1) is a float64 constant" and "the 1 in float64(1) is given the type float64". There's the section on conversions <https://golang.org/ref/spec#Conversions>, which says: A constant value x can be converted to type T if x is representable by a > value of T. That seems to read as "1 stays an untyped constant and is then converted". On the other hand, the section on constants <https://golang.org/ref/spec#Constants> says: A constant may be given a type explicitly by a constant declaration or > conversion, […] This says that the untyped constant is given a type, which seems to imply that "1 is given the type float64 by the conversion". So, it can be argued that the spec is insufficiently clear here. Personally, I tend to think that the behavior is reasonably clear - at least the part where float64(1) gives 1 the type float64. We generally accept that an untyped constant is given the type of the context it appears in. So it does take a while to chase down why it behaves this way, but it's in the spec. But either way: If anything, this is a bug in the spec, not a bug in the implementation. At this point (more than ten years after Go 1), if something requires as subtle a reading of the spec as this, it's the implementation that is right, unless implementations disagree. On Thu, Jun 3, 2021 at 11:21 AM Brian Candler <b.cand...@pobox.com> wrote: > Weird. It simplifies to this: https://play.golang.org/p/OsOhRMC6kBu > > On Thursday, 3 June 2021 at 10:08:22 UTC+1 Jamil Djadala wrote: > >> >> https://groups.google.com/g/golang-nuts >> >> package main >> >> import ( >> "fmt" >> ) >> >> func main() { >> const aa int = 0 >> var a int >> fmt.Println(float64(1<<aa), a) >> fmt.Println(float64(1<<a), a) // ./prog.go:11:21: invalid operation: >> 1 << a (shift of type float64) >> } >> ./prog.go:11:21: invalid operation: 1 << a (shift of type float64) >> > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/87ee9f5f-6db2-48e8-86cc-de0b88511a65n%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/87ee9f5f-6db2-48e8-86cc-de0b88511a65n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHs_0BXEHbUGhnZ8bcKyQU-iQ%2BaoL5SA9%2BDtiFju2%2Bxbw%40mail.gmail.com.