Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Explicitly check each interface type in core.IsAnyNilOrZero (#7168)
I introduced a bug in #7162 which lead to incorrect type comparisons. `IsAnyNilOrZero` takes a variadic amount of interfaces with each interface containing a value with underlying type `string`, `int32`, `float64`, etc and checks for that type's zero value in a switch statement. When checking for multiple numeric types on the same case statement line, the compiler will default to `int` rather than implying the type of the untyped constant `0` leading to an incorrect result at runtime. Contrast that to when each numeric type is on its own case statement line where a correct comparison can be made. Per [go.dev/blog/constants](https://go.dev/blog/constants): > The default type of an untyped constant is determined by its syntax. For string constants, the only possible implicit type is string. For [numeric constants](https://go.dev/ref/spec#Numeric_types), the implicit type has more variety. Integer constants default to int, floating-point constants float64, rune constants to rune (an alias for int32), and imaginary constants to complex128. Per [go.dev/doc/effective_go](https://go.dev/doc/effective_go#interfaces_and_types): > Constants in Go are just that—constant. They are created at compile time, even when defined as locals in functions, and can only be numbers, characters (runes), strings or booleans. Because of the compile-time restriction, the expressions that define them must be constant expressions, evaluatable by the compiler. See the following code for an explicit example. ``` package main import "fmt" func main() { for _, val := range []interface{}{1, int8(1), int16(1), int32(1), int64(1)} { switch v := val.(type) { case int, int8, int16, int32, int64: fmt.Printf("Type %T:\t%v\n", v, v == 1) } } fmt.Println("-----------------------------") for _, val := range []interface{}{1, int8(1), int16(1), int32(1), int64(1)} { switch v := val.(type) { case int: fmt.Printf("Type %T:\t%v\n", v, v == 1) case int8: fmt.Printf("Type %T:\t%v\n", v, v == 1) case int16: fmt.Printf("Type %T:\t%v\n", v, v == 1) case int32: fmt.Printf("Type %T:\t%v\n", v, v == 1) case int64: fmt.Printf("Type %T:\t%v\n", v, v == 1) } } } ------- Type int: true Type int8: false Type int16: false Type int32: false Type int64: false ----------------------------- Type int: true Type int8: true Type int16: true Type int32: true Type int64: true ```
- Loading branch information