-
Notifications
You must be signed in to change notification settings - Fork 18k
reflect: ignore blank fields in IsZero #31450
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
Comments
It seems that |
I don't think we need do to anything about this. If the |
This is the thing that strikes me as uncomfortable. And floats are generally pretty weird, so that doesn't seem very exculpatory. I guess I can see the argument either way. It is just unfortunate that being the zero value is not the same as being equal to the zero value. I guess the relevant question is what people are more likely to actually want, in practice. At a minimum we should have a sentence of documentation about this, because the distinction is subtle. And if we do decide for the "equal to" interpretation of what this function should do, then we should change floats to match (i.e. remove the |
cc @rsc since x/s/owners lists him as an owner for reflect |
I would say that not skipping The main use case I had to write a function like this was for not overriding user-defined fields in unmarshal-like methods. In which case, both ways are fine. I would say that not adding an exception like this is always better if not strictly necessary. |
This is not about adding an exception. It is about asking whether the function should be about "is the zero value" or "is equal to the zero value", and then adjusting the implementation to match. |
Well, the function is named Furthermore, checking for a loose equality is easy enough to do without this function, one can just take a real zero value and use to it to check equality. |
I looked at the equivalent usages of It could be argued that two reasonable definitions of |
I think we should rather have more guidance in the doc than no method for that. The fact that multiple people ended up writing such a function suggest that there isn't a simple and reliable way to do it and that there is a need for it. To be clear: I think it's better to add a comment along the lines |
I think we should continue to check Though perhaps the subtlety of this discussion would be a reason to not add |
I was curious about the history here so dig some digging. A bit but not much here... That's the bug that led to the current spec wording. I also found that this (https://play.golang.org/p/L3vQvIhncwZ): package main
import (
"fmt"
)
type T struct{ a, _, c int }
func main() {
t := T{1, 2, 3}
fmt.Println(t)
} ... prints |
I've tried setting the value of a blank field field, and only an I've also added tests in my branch to check
Here, the case that don't seems obvious to me is the third one rather that the fourth. Ignoring the blank field would change the fourth behavior only, but the actual implementation conforms to In light of this, I'm still in favor of checking the blank field and adding a comment. Or even a blog post detailing the issue and the choices made. (If you don't, I'll do it :P I've discovered plenty of things while doing this, and if this can encourage more people to start contributing, all the better.) |
So, anyone to take a decision here? I can add the said documentation if we reach a consensus. @ianlancetaylor @josharian @dsnet @bradfitz |
Related: #31546 |
@elwinar these kinds of decisions take time, research, and thought. |
In light of #31546, I understand :P . |
Discussed at proposal review. Now that #31546 is fixed, nothing should be able to tell whether we look at blank fields or not: the blank fields are never written. The only way this comes up is if package unsafe is involved, whether from C or doing other shenanigans. If you explicitly go out of your way to scribble a non-zero value into a blank field, it does seem like reflect.IsZero should say "that's not the zero value". It isn't, just like float64 negative zero is not the zero value. The compiler-generated hash/eq functions are implementing the == operation. IsZero is not "== zero value". It is "is the zero value" (cf float negative zero again). Let's leave IsZero as is. |
Not to object after closing, but consider this code:
It's kind of a moot point at the moment, because we currently do zero The situation described above already happens for padding. The compiler does not initialize alignment padding bytes in structs, and thus |
Change https://golang.org/cl/182617 mentions this issue: |
There is a subtle distinction between a value *being* the zero value vs being *equal to* the zero value. This was discussed at length in #31450. Using "a zero value" in the docs suggests that there may be more than zero value. That is possible on the "equal to zero value" reading, but not the "is zero" reading that we selected for the semantics of IsZero. This change attempts to prevent any confusion on this front by switching to "the zero value" in the documentation. And while we're here, eliminate a double-space. (Darn macbook keyboards.) Change-Id: Iaa02ba297438793f5a90be9919a4d53baef92f8e Reviewed-on: https://go-review.googlesource.com/c/go/+/182617 Run-TryBot: Josh Bleecher Snyder <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
I believe that the newly added reflect.IsZero (https://go-review.googlesource.com/c/go/+/171337) might need to skip struct fields named “_”. It is not possible without unsafe (or maybe reflect?) to construct a struct value with a non-zero value for a _ field. Nevertheless, I think that IsZero should skip such fields; cmd/compile’s generated equality and hash functions do.
cc @elwinar @ianlancetaylor @bradfitz
The text was updated successfully, but these errors were encountered: