The loop var change *does* break compatibility. And it did so knowingly and - as clearly explained - was an exception. Stop arguing in bad faith.
On Thu, Feb 29, 2024 at 7:03 AM tapi...@gmail.com <tapir....@gmail.com> wrote: > > > On Wednesday, February 28, 2024 at 3:19:37 PM UTC+8 Axel Wagner wrote: > > That would break backwards compatibility, though. And it would be a > re-definition (i.e. existing code would compile, but behave differently at > runtime) and is hence not allowed even under the Go 2 transition rules. > > > With Go version specified, nothing can be broken. For example, the loop > var change in Go 1.22 doesn't break backwards compatibility. (Though this > is not my opinion, ;D) > > > I'm also not sure you can exclude *all* pointers to zero-sized variables. > Note that `[0]T` is also zero-sized and you can convert slices (even empty > ones) into array-pointers. And you can take the address of struct fields. > > All of this to solve an honestly pretty small issue. It's a corner, yes. > But it isn't a particularly sharp corner. > > On Wed, Feb 28, 2024 at 8:06 AM 'Brian Candler' via golang-nuts < > golan...@googlegroups.com> wrote: > > > let's consider the two possible definitions: > > > > 1. Pointers to distinct zero-size variables are equal: [...] > > 2. Pointers to distinct zero-size variables are not equal: > > Another possibility: > > 3. Equality comparisons between pointers to zero-size variables are > forbidden at compile time. > 3a. If you wrap two such values in interfaces and try to compare them, > then you get a runtime panic, same as certain cases today > <https://go.dev/play/p/MgtUz2em65A>. > > Indeed, what if it were forbidden to take a pointer to a zero-sized > variable in the first place? There is nothing to point at, after all. > > On Wednesday 28 February 2024 at 07:17:24 UTC+7 Brien Colwell wrote: > > I think the surprising part is that the comparison result can change for > the same values because of the assumption that pointers never change. This > is implied by the spec but easy to miss. > > "Pointers to distinct zero-size variables may or may not be equal." > "Pointers to distinct zero-size variables may or may not be equal and the > results may or may not be repeatable in any context." > > Agree once a programmer is aware of the behavior it can be avoided. > > Best, > Brien > > > On Feb 27, 2024, at 3:06 PM, 'Axel Wagner' via golang-nuts < > golan...@googlegroups.com> wrote: > > On Tue, Feb 27, 2024 at 8:19 PM Marvin Renich <mr...@renich.org> wrote: > > Prior to generics, the type of the > arguments to == were easily known to the programmer, and so it was > obvious when this "undefined" exception would raise its ugly head, and > you just didn't use it for empty struct types. But now, with generics, > this can only be classified as a glaring BUG in the spec. > > > There is pretty much a 0% chance that we'd change the spec in this regard, > at this point. It would mean that variable declarations like > `[1<<30]struct{}` would have to allocate huge chunks of heap, to ensure > that different index-expressions can have different addresses. And while > there shouldn't be any code relying on that not happening for correctness, > there is definitely code out there relying on it for performance (e.g. > there is a pattern of adding struct fields like `_ [0]func()` to ensure a > type is not comparable - such a struct would now change alignment and size). > > The optimization that variables of zero size can re-use the same address > has been in Go since before Go 1. Given this, it is pretty much implied > that comparison of those pointers will sometimes have weird results - the > only question is, *which* results are weird. I agree that this is one of > the weirder cases. But I don't think we can practically define `==` for > pointers to zero-sized variables. > > I'll also point out that for generics specifically, I'm not sure *any* > action would have a practical effect. If the type argument is not > statically known, we also can't special-case it to take into account that > it's a pointer to a zero-sized variable. Note that the triggered > optimization isn't necessarily "these are pointers to zero-sized variables, > hence I can do whatever I want" - it's "these are pointers to distinct > variables, hence I can assume they are unequal". That is a generally useful > optimization and it would still be applied to generic code. > > How can a programmer count on x == y having any meaning at all in code > like this: > > func IsEqual[T comparable](x, y T) bool { > return x == y > } > > if the definition of == for empty structs is undefined? > > > The result is defined for empty structs, just not for *pointers* to empty > structs. > Note that `==` has other edge-cases as well. In particular, for floating > point/complex type arguments, `==` is irreflexive (e.g. NaN is unequal to > itself). > I'm not sure that pointers to zero-sized variables make this significantly > worse. > > > If we can at least agree that this ambiguity is no longer desirable, > > > I don't think we can agree on that, sorry. > > > let's consider the two possible definitions: > > 1. Pointers to distinct zero-size variables are equal: > > This allows the compiler to easily optimize virtual address usage, but > is inconsistent with the non-zero-size definition. > > > Please look at the issue I filed for some discussion of edge-cases we are > unlikely to be able to cover satisfactorily. One obvious case is when > converting them to `unsafe.Pointer`, in which case the compiler no longer > knows that they point at zero-sized variables. Potentially, any such > conversion would have to re-assign them the magic "zero-sized variable" > address, which then would potentially lead to other weird comparison > implications, when code assumes that two `unsafe.Pointer` pointing at > distinct variables should have distinct addresses. > > We could probably make *more* such comparisons evaluate to `true`, but > it's unlikely that we could ever cover *all* of them. It would potentially > have prohibitive performance-impact on slicing operations, for example. > > 2. Pointers to distinct zero-size variables are not equal: > > This is consistent with the non-zero-size definition, but the > implementation would likely require distinct virtual addresses for > distinct variables. Whether this would require committed memory > corresponding to those virtual addresses is unclear to me. > > > I believe it would. In effect, `struct{}` would have to take at least one > byte (as would a zero-sized array). > > > Definition 1 removes the distinction between empty struct values and > empty struct instances, and the only way for the programmer to get that > distinction back is by using a non-empty struct. > > On the other hand, definition 2 preserves the distinction. If a > programmer wants to have instances compare as equal, it is often very > easy to use instances of the empty type rather than instances of a > pointer to the empty type. Implement the methods on the type with value > receivers rather than pointer receivers. > > > I think if these arguments hold any water, the argument "the programmer > just shouldn't use pointers to zero-sized variables, if they want defined > semantics for ==" is just as valid. That is, if they have control over the > type and we are willing to force them to make a decision aligning with our > definition, why not force them to make a decision aligning with there not > being a definition? > > > > ...Marvin > > -- > 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...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/Zd41i3rHLskqBuef%40basil.wdw > . > > > -- > > You received this message because you are subscribed to a topic in the > Google Groups "golang-nuts" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/golang-nuts/JBVqWYFdtC4/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > golang-nuts...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHVuxSduyWHG20DjzG1jvE0P06fEqC_FyHdDEWewjOjTg%40mail.gmail.com > <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHVuxSduyWHG20DjzG1jvE0P06fEqC_FyHdDEWewjOjTg%40mail.gmail.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...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/c7ead734-8ce6-4254-91ac-771b02e527ddn%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/c7ead734-8ce6-4254-91ac-771b02e527ddn%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/c7b44255-13f1-434d-b569-f592c8e262d4n%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/c7b44255-13f1-434d-b569-f592c8e262d4n%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/CAEkBMfHJvxBpRHzrre8CryN9vJRcrM8H%3DifS5%3DBgELjsor7s3g%40mail.gmail.com.