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.

Reply via email to