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.