-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
proposal: Go 2: spec: always permit comparisons against zero value of type #26842
Comments
Does the zero value need to be static? Or it can be dynamic, as long as at run time, at the point of ==, the value is zero? From https://play.golang.org/p/JOmxaVJoYtT,
it seems to suggest that the zero value does not have to be static (it is a variable). What if the value is not zero, then? Panic? |
One side would need to be known to be zero statically. Having a universal zero like in the linked issue would be the easiest way to achieve that. |
Let's look at
It should be transferred to something like
This is not the same as |
As mentioned in #35966, another solution would be a |
A related issue is that you can't define a const which is a nil func/slice because you can't define const func/slices: const zero func() = nil // does not compile So, as of now, the only way to write I think generics will require Go to either add an isZero() generic built-in or a "universal zero" identifier. |
I'm running into a scenario right now where this would be extremely useful. What is the current intention and/or best practice for this problem if |
You can fake it with reflect. See #35966 for discussion of solutions. |
@carlmjohnson the reflect option is very slow when it comes to structs :/ |
Yes, that's why I am pushing for #35966 to happen. |
I posted this in the func Zero[T any](v T) bool {
bp := (*byte)(unsafe.Pointer(&v))
sz := unsafe.Sizeof(v)
for _, v := range unsafe.Slice(bp, sz) {
if v != 0 {
return false
}
}
return true
} |
Note that there some subtleties here around padding and fields named |
f := math.Copysign(0, -1)
fmt.Println(ZeroAny(f), ZeroGeneric(f)) // false true |
@josharian it looks like the decision was those are going to be kept zero for now? If I'm reading that correctly there's a hypothetical flaw in the naive check but nothing that can manifest today. Did I get that correct? @carlmjohnson that is a fair point. It looks like reflect.IsZero handles that correctly but that float/complex are the only cases where this is wrong. That can't really be worked around today without doing something like this: https://github.com/zephyrtronium/number/blob/main/reflect.go#L32 Disappointing! |
For comparable types, the compiler generates |
Fixed by acceptance of #61372 |
Go, effectively, has three-kinds of comparability:
==
operator defined for a type (structs and arrays with incomparable fields).==
operator but it can only test against the zero value (funcs, maps, and slices can be compared againstnil
). The spec treats these as incomparable types and notes the special case.==
operator and it works for all valuesWhen writing code with known types, this is not an issue. You know if there's an
==
operator and whether you can compare against all values or just the zero value.When generating code (or, possibly in the future, writing generic code) over arbitrary types, this asymmetry is a bit more bothersome. You can't just classify types as comparable or incomparable, you need to handle the 0-comparable case as well even though it is so similar: https://play.golang.org/p/JOmxaVJoYtT
I propose collapsing incomparable and 0-comparable. Allow incomparable structs and arrays to be compared to their zero value. There would always be an
==
operator and it would always be safe to compare any value to zero. Care would still need to be taken to ensure comparability when using==
between arbitrary values, but the simpler classification eases matters.I believe this would be a 100% backwards-compatible change and perhaps even simplify the spec a bit (or at least not require too many changes).
The concerns would be go/types and reflect, but they both seem to lump what I call 0-comparability in with incomparability, but there, admittedly, could be subtler implications.
This is tangentially related to defining a universal zero value #19642 (comment) in that similar arguments are involved and the two would compliment each other.
The text was updated successfully, but these errors were encountered: