FWIW I believe there is enough subtlety here (small changes in the code might trigger different compiler optimizations) that I wouldn't rely too much on probing the compiler with different programs. Instead, I'd suggest decompiling the binary and/or running it in a debugger, to check what the actual pointers are. From looking at godbolt, AIUI the compiler is optimizing the comparison into a constant: https://go.godbolt.org/z/x1Ef3PxPb
Though, really, I don't think this is *super* weird. Like, don't get me wrong, the behavior is counter-intuitive. But once you've accepted that "comparison of pointers to zero-sized variables is not really defined", the actual myriads of ways in which it behaves counter-intuitively become less important. On Sat, Feb 24, 2024 at 5:28 PM jake...@gmail.com <jake6...@gmail.com> wrote: > What is really fantastical is that a==b prints false, even though the > pointers are actually the same. I am guessing some sort of optimization > effect is at play here. > > https://go.dev/play/p/Dsqeh_aAXKT > > type Foo struct { > } > > func main() { > > a := &Foo{} > b := &Foo{} > fmt.Printf("%t\n", *a == *b) > fmt.Printf("%t\n", a == b) > q := uintptr(unsafe.Pointer(a)) > r := uintptr(unsafe.Pointer(b)) > //fmt.Printf("%p %p\n", a, b) > fmt.Printf("%t\n", q == r) > fmt.Printf("%x %x\n", q, r) > } > > prints: > > true > false > true > c000104ee0 c000104ee0 > > wild! (or am I missing something?) > On Thursday, February 22, 2024 at 1:07:08 PM UTC-5 Axel Wagner wrote: > >> On Thu, Feb 22, 2024 at 6:44 PM burak serdar <bse...@computer.org> wrote: >> >>> Maybe the spec should be clarified to say "for a compilation of a >>> program, two pointers to zero-size variables may or may not be equal", >>> because otherwise it implies that if you have >>> >>> x:= a==b >>> y:= a==b >>> >>> x may or may not be true. >> >> >> Well, given that the spec is *not* saying what you say it maybe should - >> it seems we are in agreement. It is indeed correct for `x` to may or not be >> equal to `y` here, with the spec as it is right now. >> >> >>> If a==b, then that should hold for every >>> execution of that program, and throughout the program. >>> >>> >>> > >>> >> >>> >> That is, if a==b, then >>> >> interface{}(a)==interface{}(b), and vice versa. But what we have here >>> >> is a!=b but interface{}(a)==interface{}(b) >>> >> >>> >> On Thu, Feb 22, 2024 at 9:50 AM Axel Wagner >>> >> <axel.wa...@googlemail.com> wrote: >>> >> > >>> >> > Hm actually, the spec allows for this, technically speaking: >>> https://go.dev/ref/spec#Comparison_operators >>> >> > >>> >> > > Pointers to distinct zero-size variables may or may not be equal. >>> >> > >>> >> > Arguably, this genuinely would allow comparison of pointers to >>> zero-sized variables to have any behavior whatsoever (including being >>> random). But it certainly is confusing. >>> >> > >>> >> > >>> >> > On Thu, Feb 22, 2024 at 5:46 PM Axel Wagner < >>> axel.wa...@googlemail.com> wrote: >>> >> >> >>> >> >> I see. Sorry, I was jumping to conclusions and didn't quite get >>> what you mean. That is my fault. >>> >> >> >>> >> >> I agree that this looks confusing and is arguably a bug. I filed >>> https://github.com/golang/go/issues/65878, thanks for pointing it out. >>> >> >> >>> >> >> On Thu, Feb 22, 2024 at 5:20 PM burak serdar <bse...@computer.org> >>> wrote: >>> >> >>> >>> >> >>> Creating an interface is not creating a pointer to a zero sized >>> variable. >>> >> >>> >>> >> >>> a==b prints false. That means, a and b point to different >>> locations >>> >> >>> Bar(a)==Bar(b) prints true. If a!=b, then Bar(a) must be >>> different from Bar(b) >>> >> >>> >>> >> >>> On Thu, Feb 22, 2024 at 9:15 AM Axel Wagner >>> >> >>> <axel.wa...@googlemail.com> wrote: >>> >> >>> > >>> >> >>> > If you expect that, you are misreading the spec. There is no >>> guarantee of any behavior here. An implementation is allowed to flip a >>> coin, every time you create a pointer to a zero-sized variable, and either >>> return a unique pointer or a singleton. I think you may assume that &a == >>> &a, always. But apart from that, who knows. >>> >> >>> > >>> >> >>> > Zero-sized variables *may* have the same address. They don't >>> *have* to. >>> >> >>> > >>> >> >>> > On Thu, Feb 22, 2024 at 5:12 PM burak serdar < >>> bse...@computer.org> wrote: >>> >> >>> >> >>> >> >>> >> On Thu, Feb 22, 2024 at 9:00 AM Axel Wagner >>> >> >>> >> <axel.wa...@googlemail.com> wrote: >>> >> >>> >> > >>> >> >>> >> > Note that in the Spec section I quoted above it says "Two >>> distinct zero-size variables may have the same address in memory" (emphasis >>> mine). >>> >> >>> >> > There is no guarantee, that all zero-sized values have the >>> same address (otherwise, you'd get into inefficiencies when taking the >>> address of a zero-sized field in a larger struct, or when converting a >>> zero-capacity slice into an array-pointer). But it is allowed. >>> >> >>> >> > If you require two pointers returned from different code >>> paths to be different, for correctness, then you have to make them point at >>> something that has non-zero size. Otherwise, all potential combinations are >>> valid according to the spec. >>> >> >>> >> >>> >> >>> >> Yes. But in that case, you'd expect either a==b and >>> Bar(a)==Bar(b) to >>> >> >>> >> be both true, or both false. In this case, one is true and the >>> other >>> >> >>> >> is not. >>> >> >>> >> >>> >> >>> >> >>> >> >>> >> > >>> >> >>> >> > On Thu, Feb 22, 2024 at 4:53 PM burak serdar < >>> bse...@computer.org> wrote: >>> >> >>> >> >> >>> >> >>> >> >> The compiler can allocate the same address for empty >>> structs, so I >>> >> >>> >> >> actually expected a==b to be true, not false. However, >>> there's >>> >> >>> >> >> something more interesting going on here because: >>> >> >>> >> >> >>> >> >>> >> >> a := &Foo{} >>> >> >>> >> >> b := &Foo{} >>> >> >>> >> >> fmt.Printf("%t\n", *a == *b) >>> >> >>> >> >> fmt.Printf("%t\n", a == b) >>> >> >>> >> >> fmt.Printf("%p %p\n", a, b) >>> >> >>> >> >> x := Bar(a) >>> >> >>> >> >> y := Bar(b) >>> >> >>> >> >> fmt.Printf("%t\n", Bar(a) == Bar(b)) >>> >> >>> >> >> fmt.Printf("%t\n", x == y) >>> >> >>> >> >> >>> >> >>> >> >> Prints: >>> >> >>> >> >> >>> >> >>> >> >> true >>> >> >>> >> >> true >>> >> >>> >> >> 0x58e360 0x58e360 // Note that a and be are pointing to the >>> same address >>> >> >>> >> >> true >>> >> >>> >> >> true >>> >> >>> >> >> >>> >> >>> >> >> >>> >> >>> >> >> But: >>> >> >>> >> >> a := &Foo{} >>> >> >>> >> >> b := &Foo{} >>> >> >>> >> >> fmt.Printf("%t\n", *a == *b) >>> >> >>> >> >> fmt.Printf("%t\n", a == b) >>> >> >>> >> >> //fmt.Printf("%p %p\n", a, b) // Comment out the print >>> >> >>> >> >> x := Bar(a) >>> >> >>> >> >> y := Bar(b) >>> >> >>> >> >> fmt.Printf("%t\n", Bar(a) == Bar(b)) >>> >> >>> >> >> fmt.Printf("%t\n", x == y) >>> >> >>> >> >> >>> >> >>> >> >> >>> >> >>> >> >> Prints: >>> >> >>> >> >> >>> >> >>> >> >> true >>> >> >>> >> >> false >>> >> >>> >> >> true >>> >> >>> >> >> true >>> >> >>> >> >> >>> >> >>> >> >> >>> >> >>> >> >> On Thu, Feb 22, 2024 at 3:56 AM Brien Colwell < >>> xcol...@gmail.com> wrote: >>> >> >>> >> >> > >>> >> >>> >> >> > I'm confused by this output. It appears that the >>> interface of two different pointers to an empty struct are equal. In all >>> other cases, interface equality seems to be the pointer equality. What's >>> going on in the empty struct case? >>> >> >>> >> >> > >>> >> >>> >> >> > ``` >>> >> >>> >> >> > package main >>> >> >>> >> >> > >>> >> >>> >> >> > import "fmt" >>> >> >>> >> >> > >>> >> >>> >> >> > type Foo struct { >>> >> >>> >> >> > } >>> >> >>> >> >> > >>> >> >>> >> >> > func (self *Foo) Hello() { >>> >> >>> >> >> > } >>> >> >>> >> >> > >>> >> >>> >> >> > type FooWithValue struct { >>> >> >>> >> >> > A int >>> >> >>> >> >> > } >>> >> >>> >> >> > >>> >> >>> >> >> > func (self *FooWithValue) Hello() { >>> >> >>> >> >> > } >>> >> >>> >> >> > >>> >> >>> >> >> > type Bar interface { >>> >> >>> >> >> > Hello() >>> >> >>> >> >> > } >>> >> >>> >> >> > >>> >> >>> >> >> > func main() { >>> >> >>> >> >> > a := &Foo{} >>> >> >>> >> >> > b := &Foo{} >>> >> >>> >> >> > fmt.Printf("%t\n", *a == *b) >>> >> >>> >> >> > fmt.Printf("%t\n", a == b) >>> >> >>> >> >> > fmt.Printf("%t\n", Bar(a) == Bar(b)) >>> >> >>> >> >> > >>> >> >>> >> >> > c := &FooWithValue{A: 1} >>> >> >>> >> >> > d := &FooWithValue{A: 1} >>> >> >>> >> >> > fmt.Printf("%t\n", *c == *d) >>> >> >>> >> >> > fmt.Printf("%t\n", c == d) >>> >> >>> >> >> > fmt.Printf("%t\n", Bar(c) == Bar(d)) >>> >> >>> >> >> > } >>> >> >>> >> >> > ``` >>> >> >>> >> >> > >>> >> >>> >> >> > Prints (emphasis added on the strange case): >>> >> >>> >> >> > >>> >> >>> >> >> > ``` >>> >> >>> >> >> > true >>> >> >>> >> >> > false >>> >> >>> >> >> > **true** >>> >> >>> >> >> > true >>> >> >>> >> >> > false >>> >> >>> >> >> > false >>> >> >>> >> >> > ``` >>> >> >>> >> >> > >>> >> >>> >> >> > >>> >> >>> >> >> > -- >>> >> >>> >> >> > 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/d93760c9-61a7-4a3c-9b5c-d89f023d2253n%40googlegroups.com >>> . >>> >> >>> >> >> >>> >> >>> >> >> -- >>> >> >>> >> >> 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/CAMV2Rqrq21ymUJ00ni_JV%3Dkv6itqZg51GoWM5zJNjcGU1BKcuA%40mail.gmail.com >>> . >>> >> -- > 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/682fbdcb-546c-4f38-81e8-f9fcfc8f0403n%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/682fbdcb-546c-4f38-81e8-f9fcfc8f0403n%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/CAEkBMfEznZ9MbysCXhcge_54itPiyyDKrUYEYLMJBU0UnCtAaA%40mail.gmail.com.