Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-26 Thread Ian Lance Taylor
On Tue, Jun 25, 2024 at 9:37 PM 'Axel Wagner' via golang-nuts
 wrote:
>
> you might be interested to learn that Ian has filed a CL adding an FAQ entry.

Now committed at https://go.dev/doc/faq#zero_size_types .

Ian

-- 
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/CAOyqgcVrREsxZK0dA3RqE%2B8_D7HDvJuSmeAo2aE2fga1k7UTCA%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-25 Thread 'Axel Wagner' via golang-nuts
Hi,

you might be interested to learn that Ian has filed a CL adding an FAQ entry
.

On Thu, 20 Jun 2024 at 16:18, Oliver Eikemeier 
wrote:

> Thanks for that example.
>
> The issue is that you and I have constructed aliased variables that the
> optimizer assumes are not aliased. Therefore the “false” on comparison,
> which also happens with pointers to zero-sized variables, but is much more
> common in the latter case.
>
> This is interesting. I’m not enough of a compiler buff to say that this
> assumption is reasonable - Go is 14 years old, so it seems to work - but
> obviously one can write code where it is false, the “zero-sized pointers”
> being the most prominent example. Anyone has a pointer to the alias
> analysis design of the Go compiler?
>
> Am 20.06.2024 um 15:57 schrieb Axel Wagner  >:
>
> I don't believe the issue in this case really is to do with zero-sized
> variables. Here is an example with the same output, not involving any
> zero-sized variables:
> https://go.dev/play/p/JzbwbVqBR0k
> The issue is that you treat a `*struct{}` as an `*int` - that is, you
> explicitly obtain a pointer to invalid memory - and then expect that to
> have any reasonable behaviour.
>
>
>

-- 
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/CAEkBMfFJUJQcSid7WGTcz%3DnL8L8MfLy%3D_4s43qJvReqP1hCcUw%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread 'Axel Wagner' via golang-nuts
I want to re-emphasise that both of these examples violate the allowed
usages of unsafe.Pointer defined by gc. So I would argue that, yes, its
expectation is reasonable, because it explicitly told you not to create
this situation.

If you can construct a program that does not violate the unsafe.Pointer
rules and yet behaves unexpectedly, the question might be more ambiguous.

On Thu 20. Jun 2024 at 16:18, Oliver Eikemeier 
wrote:

> Thanks for that example.
>
> The issue is that you and I have constructed aliased variables that the
> optimizer assumes are not aliased. Therefore the “false” on comparison,
> which also happens with pointers to zero-sized variables, but is much more
> common in the latter case.
>
> This is interesting. I’m not enough of a compiler buff to say that this
> assumption is reasonable - Go is 14 years old, so it seems to work - but
> obviously one can write code where it is false, the “zero-sized pointers”
> being the most prominent example. Anyone has a pointer to the alias
> analysis design of the Go compiler?
>
> Am 20.06.2024 um 15:57 schrieb Axel Wagner  >:
>
> I don't believe the issue in this case really is to do with zero-sized
> variables. Here is an example with the same output, not involving any
> zero-sized variables:
> https://go.dev/play/p/JzbwbVqBR0k
> The issue is that you treat a `*struct{}` as an `*int` - that is, you
> explicitly obtain a pointer to invalid memory - and then expect that to
> have any reasonable behaviour.
>
>
>

-- 
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/CAEkBMfGqXfeeU32z1tetauvH91u4iZSocKd3j2127tiSqGY2QQ%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Oliver Eikemeier


> Am 20.06.2024 um 14:12 schrieb Axel Wagner :
> 
> On Thu, 20 Jun 2024 at 13:48, Oliver Eikemeier  > wrote:
> 
> I think you should acknowledge that the spec *is* already trying to be very 
> clear about this. The fact that you can poke holes in it is because writing a 
> spec unambiguously is hard.

I acknowledge that - that’s why I care in the first place and also - as 
mentioned - try not to be stubborn. Although the latter is not always easy in 
internet discussions, but I digress.

> But the two quoted phrases are there in the best attempt to clearly state 
> that you can not rely on any assumptions about pointers to zero-sized 
> variables - within the somewhat abstract framework of the spec. Feel free to 
> propose a better one, I'm not actually arguing against that.

Yeah, I’m still trying to understand the issue, the discussion helps, so thanks 
for that.

> Am 20.06.2024 um 14:21 schrieb Robert Engels :
> 
> I would add that I think the Go team should strive to remove as much 
> “implementation defined” or “undefined” from the spec as possible. Forgo the 
> optimizations. It’s this language that makes C++ such a pain to work with 
> especially in a cross platform manner.
> 
> I think you can safely narrow the spec in this area without issue - since it 
> would have been very difficult to use anyway. Maybe some highly specialized 
> code that relied on a particular Go implementation might. 

What happens seems to be:

a) In practice the runtime just uses pointers as memory addresses, so 
everything is fine there.

b) Pointers (especially unsafe pointers) being address in memory (not only “a 
storage location for holding a value”) is not really specified, but sometimes 
useful. The standard runtime uses casting of unsafe pointer for multiple 
reasons.

c) Pointers to zero sized variables have to point somewhere. Since the variable 
has zero size, some aliasing is easily possible.

d) The optimizer is free to make assumptions about aliasing that sometimes 
don’t match the memory alignment during runtime, disagreeing with a).

I’m not advocating against the optimizer making assumptions about aliasing that 
are not true, it seems useful to me.

On the other hand you can do surprising constructs (Go Playground 
):

func f7() {
var (
a  struct{}
b  int
aa = (*int)(unsafe.Pointer())
ba = (*int)(unsafe.Pointer())
)

println(":", aa, reflect.TypeOf(aa).String())
println(":", ba, reflect.TypeOf(ba).String())

*ba = 0

*aa++
println(*ba, aa == ba)

*ba++
println(*aa, ba == aa)
}

: 0xc466f8 *int
: 0xc466f8 *int
0 false
2 false

There are definitely dragons. I might need some more time to think over this, 
but thanks to every participant for the useful input.

Cheers
Oliver

-- 
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/E0D19A9C-4434-4CEB-B154-B10CD3959A61%40fillmore-labs.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Robert Engels
What I asked did not require the first, I was referring more about the latter. So regardless of how it is implemented it is always false. On Jun 20, 2024, at 7:39 AM, Axel Wagner  wrote:On Thu, 20 Jun 2024 at 14:21, Robert Engels  wrote:I would add that I think the Go team should strive to remove as much “implementation defined” or “undefined” from the spec as possible. Forgo the optimizations. It’s this language that makes C++ such a pain to work with especially in a cross platform manner. I think you can safely narrow the spec in this area without issue - since it would have been very difficult to use anyway. Maybe some highly specialized code that relied on a particular Go implementation might. I strongly disagree. There is a lot of software out there that relies on zero-sized fields to achieve certain semantic behaviours (like preventing copying or using unkeyed struct literals) or alignments. They all assume that the size of a struct is not impacted by that. Without this "optimization" that would no longer be true and every zero-sized field must take at least one byte of memory, to be able to guarantee that they have different addresses. That is just not going to happen.On the other hand, removing the restriction in the other direction and just always making it false is what I suggested last time and there are reasons in that issue, why that isn't going to happen either. On Jun 20, 2024, at 7:12 AM, 'Axel Wagner' via golang-nuts  wrote:On Thu, 20 Jun 2024 at 13:48, Oliver Eikemeier  wrote:Am 20.06.2024 um 13:24 schrieb Axel Wagner :We can see that 1. `unsafe.Pointer` is definitionally a pointer type, 2. in your example, the two `unsafe.Pointers` do not point to the same variable and do not have the value `nil` and 3. are not pointing at distinct zero-sized variables. So their comparison should be `false`, which is what your example observes.Does it (Go Playground)?func f5() {	var (		a  struct{}		b  int		aa = (*int)(unsafe.Pointer())		ba = (*int)(unsafe.Pointer())		eq = aa == ba	)	println(":", aa, reflect.TypeOf(aa).String())	println(":", ba, reflect.TypeOf(ba).String())	println(" == :", eq)	cmpIntPtr(aa, ba)}func cmpIntPtr(p1 *int, p2 *int) {	fmt.Println("p1 == p2:", p1 == p2)}: 0xc466f8 *int
: 0xc466f8 *int
 == : false
p1 == p2: trueInterestingly, the spec does not forbid that (or specifies it as implementation-defined), though the (implementation-defined) unsafe.Pointer rules
 do, as using `unsafe.Pointer` to convert between pointers of different 
base types is only allowed if the target variable is at least as large 
as the source variable and both share an equivalent memory layout.I
 think the fact that the spec does not put any limits on the allowed 
behaviour of converting between `unsafe.Pointer` and other pointer types
 is a clear oversight that should be corrected (perhaps it should really
 be "The effect of converting between Pointer and uintptr is 
implementation-defined" should really say "and other types"). But I 
don't think it's a surprising fact that you can make a program behave in almost arbitrary ways by doing that. I’m advocating for at least a FAQ article,I tend to agree, though I'm not sure how to phrase that, beyond saying "do not make any assumptions about the identity pointers to zero-sized variables or with zero-sized base types or that where derived from one of those" and I'm not sure how helpful that is.It seems like a frequently asked question to me ;)It is. But note that every time it is asked, it leads to considerable discussion, which seems to strongly suggest that it is hard to give a simple, unambiguous answer that people find satisfying.I think you should acknowledge that the spec *is* already trying to be very clear about this. The fact that you can poke holes in it is because writing a spec unambiguously is hard. But the two quoted phrases are there in the best attempt to clearly state that you can not rely on any assumptions about pointers to zero-sized variables - within the somewhat abstract framework of the spec. Feel free to propose a better one, I'm not actually arguing against that.And I'm also not arguing against an FAQ entry. Ideally, someone would suggest a phrasing that is sufficiently broad and unambiguous and clear to cover any version of this question people might ask, while also not contradicting the spec. but also think the specification should be adapted, for clarity but also for the fact that only one pointer pointing to a zero-sized variable can compare differently to anything over time, even things having the same address value.Note that "address value" is not something that exists within the spec. As for clarifying the spec here, maybe. I do think the behavior is covered, as I outlined above. And as above, I'm not sure how to clarify it further, while still leaving up the space we want to left open.I vote for making this 

Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread 'Axel Wagner' via golang-nuts
FYI, filed https://github.com/golang/go/issues/68086 for the spec-hole that
conversions between unsafe.Pointer and other pointer types are not
implementation defined.

On Thu, 20 Jun 2024 at 14:12, Axel Wagner 
wrote:

>
>
> On Thu, 20 Jun 2024 at 13:48, Oliver Eikemeier <
> eikeme...@fillmore-labs.com> wrote:
>
>>
>> Am 20.06.2024 um 13:24 schrieb Axel Wagner > >:
>>
>> We can see that 1. `unsafe.Pointer` is definitionally a pointer type, 2.
>> in your example, the two `unsafe.Pointers` do not point to the same
>> variable and do not have the value `nil` and 3. are not pointing at
>> distinct zero-sized variables. So their comparison should be `false`, which
>> is what your example observes.
>>
>>
>> Does it (Go Playground )?
>>
>> func f5() {
>> var (
>> a  struct{}
>> b  int
>> aa = (*int)(unsafe.Pointer())
>> ba = (*int)(unsafe.Pointer())
>> eq = aa == ba
>> )
>>
>> println(":", aa, reflect.TypeOf(aa).String())
>> println(":", ba, reflect.TypeOf(ba).String())
>> println(" == :", eq)
>> cmpIntPtr(aa, ba)
>> }
>>
>> func cmpIntPtr(p1 *int, p2 *int) {
>> fmt.Println("p1 == p2:", p1 == p2)
>> }
>>
>> : 0xc466f8 *int
>> : 0xc466f8 *int
>>  == : falsep1 == p2: true
>>
>>
> Interestingly, the spec does not forbid that (or specifies it as
> implementation-defined), though the (implementation-defined)
> unsafe.Pointer rules  do, as using
> `unsafe.Pointer` to convert between pointers of different base types is
> only allowed if the target variable is at least as large as the source
> variable and both share an equivalent memory layout.
>
> I think the fact that the spec does not put any limits on the allowed
> behaviour of converting between `unsafe.Pointer` and other pointer types is
> a clear oversight that should be corrected (perhaps it should really be
> "The effect of converting between Pointer and uintptr is
> implementation-defined" should really say "and other types"). But I don't
> think it's a surprising fact that you can make a program behave in almost
> arbitrary ways by doing that.
>
>
>> I’m advocating for at least a FAQ article,
>>
>>
>> I tend to agree, though I'm not sure how to phrase that, beyond saying
>> "do not make any assumptions about the identity pointers to zero-sized
>> variables or with zero-sized base types or that where derived from one of
>> those" and I'm not sure how helpful that is.
>>
>>
>> It seems like a frequently asked question to me ;)
>>
>
> It is. But note that every time it is asked, it leads to considerable
> discussion, which seems to strongly suggest that it is hard to give a
> simple, unambiguous answer that people find satisfying.
>
> I think you should acknowledge that the spec *is* already trying to be
> very clear about this. The fact that you can poke holes in it is because
> writing a spec unambiguously is hard. But the two quoted phrases are there
> in the best attempt to clearly state that you can not rely on any
> assumptions about pointers to zero-sized variables - within the somewhat
> abstract framework of the spec. Feel free to propose a better one, I'm not
> actually arguing against that.
>
> And I'm also not arguing against an FAQ entry. Ideally, someone would
> suggest a phrasing that is sufficiently broad and unambiguous and clear to
> cover any version of this question people might ask, while also not
> contradicting the spec.
>
>
>> but also think the specification should be adapted, for clarity but also
>>> for the fact that only one pointer pointing to a zero-sized variable can
>>> compare differently to anything over time, even things having the same
>>> address value.
>>>
>>
>> Note that "address value" is not something that exists within the spec.
>> As for clarifying the spec here, maybe. I do think the behavior is covered,
>> as I outlined above. And as above, I'm not sure how to clarify it further,
>> while still leaving up the space we want to left open.
>>
>>
>> I vote for making this openness explicit, meaning that even the optimizer
>> is free to make assumptions that do not hold during runtime. So if you have
>> a pointer derived from something pointing to a zero-size type it can
>> compare with different results over time, even false when having the same
>> value. I do not believe that is what’s currently in the spec.
>>
>
>> Cheers
>> Oliver
>>
>>

-- 
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/CAEkBMfGEJivxGLb6iEWMri0Szesf8EgVwR%2BV9CVCbv0rRvo15Q%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Robert Engels
I would add that I think the Go team should strive to remove as much “implementation defined” or “undefined” from the spec as possible. Forgo the optimizations. It’s this language that makes C++ such a pain to work with especially in a cross platform manner. I think you can safely narrow the spec in this area without issue - since it would have been very difficult to use anyway. Maybe some highly specialized code that relied on a particular Go implementation might. On Jun 20, 2024, at 7:12 AM, 'Axel Wagner' via golang-nuts  wrote:On Thu, 20 Jun 2024 at 13:48, Oliver Eikemeier  wrote:Am 20.06.2024 um 13:24 schrieb Axel Wagner :We can see that 1. `unsafe.Pointer` is definitionally a pointer type, 2. in your example, the two `unsafe.Pointers` do not point to the same variable and do not have the value `nil` and 3. are not pointing at distinct zero-sized variables. So their comparison should be `false`, which is what your example observes.Does it (Go Playground)?func f5() {	var (		a  struct{}		b  int		aa = (*int)(unsafe.Pointer())		ba = (*int)(unsafe.Pointer())		eq = aa == ba	)	println(":", aa, reflect.TypeOf(aa).String())	println(":", ba, reflect.TypeOf(ba).String())	println(" == :", eq)	cmpIntPtr(aa, ba)}func cmpIntPtr(p1 *int, p2 *int) {	fmt.Println("p1 == p2:", p1 == p2)}: 0xc466f8 *int
: 0xc466f8 *int
 == : false
p1 == p2: trueInterestingly, the spec does not forbid that (or specifies it as implementation-defined), though the (implementation-defined) unsafe.Pointer rules
 do, as using `unsafe.Pointer` to convert between pointers of different 
base types is only allowed if the target variable is at least as large 
as the source variable and both share an equivalent memory layout.I
 think the fact that the spec does not put any limits on the allowed 
behaviour of converting between `unsafe.Pointer` and other pointer types
 is a clear oversight that should be corrected (perhaps it should really
 be "The effect of converting between Pointer and uintptr is 
implementation-defined" should really say "and other types"). But I 
don't think it's a surprising fact that you can make a program behave in almost arbitrary ways by doing that. I’m advocating for at least a FAQ article,I tend to agree, though I'm not sure how to phrase that, beyond saying "do not make any assumptions about the identity pointers to zero-sized variables or with zero-sized base types or that where derived from one of those" and I'm not sure how helpful that is.It seems like a frequently asked question to me ;)It is. But note that every time it is asked, it leads to considerable discussion, which seems to strongly suggest that it is hard to give a simple, unambiguous answer that people find satisfying.I think you should acknowledge that the spec *is* already trying to be very clear about this. The fact that you can poke holes in it is because writing a spec unambiguously is hard. But the two quoted phrases are there in the best attempt to clearly state that you can not rely on any assumptions about pointers to zero-sized variables - within the somewhat abstract framework of the spec. Feel free to propose a better one, I'm not actually arguing against that.And I'm also not arguing against an FAQ entry. Ideally, someone would suggest a phrasing that is sufficiently broad and unambiguous and clear to cover any version of this question people might ask, while also not contradicting the spec. but also think the specification should be adapted, for clarity but also for the fact that only one pointer pointing to a zero-sized variable can compare differently to anything over time, even things having the same address value.Note that "address value" is not something that exists within the spec. As for clarifying the spec here, maybe. I do think the behavior is covered, as I outlined above. And as above, I'm not sure how to clarify it further, while still leaving up the space we want to left open.I vote for making this openness explicit, meaning that even the optimizer is free to make assumptions that do not hold during runtime. So if you have a pointer derived from something pointing to a zero-size type it can compare with different results over time, even false when having the same value. I do not believe that is what’s currently in the spec. CheersOliver



-- 
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/CAEkBMfGOWoQYrQ9qm_9%2BdyvEObJV3JP%2BhwwFj9%2Bgo%3DqusRVL7A%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 

Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread 'Axel Wagner' via golang-nuts
On Thu, 20 Jun 2024 at 13:48, Oliver Eikemeier 
wrote:

>
> Am 20.06.2024 um 13:24 schrieb Axel Wagner  >:
>
> We can see that 1. `unsafe.Pointer` is definitionally a pointer type, 2.
> in your example, the two `unsafe.Pointers` do not point to the same
> variable and do not have the value `nil` and 3. are not pointing at
> distinct zero-sized variables. So their comparison should be `false`, which
> is what your example observes.
>
>
> Does it (Go Playground )?
>
> func f5() {
> var (
> a  struct{}
> b  int
> aa = (*int)(unsafe.Pointer())
> ba = (*int)(unsafe.Pointer())
> eq = aa == ba
> )
>
> println(":", aa, reflect.TypeOf(aa).String())
> println(":", ba, reflect.TypeOf(ba).String())
> println(" == :", eq)
> cmpIntPtr(aa, ba)
> }
>
> func cmpIntPtr(p1 *int, p2 *int) {
> fmt.Println("p1 == p2:", p1 == p2)
> }
>
> : 0xc466f8 *int
> : 0xc466f8 *int
>  == : falsep1 == p2: true
>
>
Interestingly, the spec does not forbid that (or specifies it as
implementation-defined), though the (implementation-defined) unsafe.Pointer
rules  do, as using `unsafe.Pointer` to
convert between pointers of different base types is only allowed if the
target variable is at least as large as the source variable and both share
an equivalent memory layout.

I think the fact that the spec does not put any limits on the allowed
behaviour of converting between `unsafe.Pointer` and other pointer types is
a clear oversight that should be corrected (perhaps it should really be
"The effect of converting between Pointer and uintptr is
implementation-defined" should really say "and other types"). But I don't
think it's a surprising fact that you can make a program behave in almost
arbitrary ways by doing that.


> I’m advocating for at least a FAQ article,
>
>
> I tend to agree, though I'm not sure how to phrase that, beyond saying "do
> not make any assumptions about the identity pointers to zero-sized
> variables or with zero-sized base types or that where derived from one of
> those" and I'm not sure how helpful that is.
>
>
> It seems like a frequently asked question to me ;)
>

It is. But note that every time it is asked, it leads to considerable
discussion, which seems to strongly suggest that it is hard to give a
simple, unambiguous answer that people find satisfying.

I think you should acknowledge that the spec *is* already trying to be very
clear about this. The fact that you can poke holes in it is because writing
a spec unambiguously is hard. But the two quoted phrases are there in the
best attempt to clearly state that you can not rely on any assumptions
about pointers to zero-sized variables - within the somewhat abstract
framework of the spec. Feel free to propose a better one, I'm not actually
arguing against that.

And I'm also not arguing against an FAQ entry. Ideally, someone would
suggest a phrasing that is sufficiently broad and unambiguous and clear to
cover any version of this question people might ask, while also not
contradicting the spec.


> but also think the specification should be adapted, for clarity but also
>> for the fact that only one pointer pointing to a zero-sized variable can
>> compare differently to anything over time, even things having the same
>> address value.
>>
>
> Note that "address value" is not something that exists within the spec. As
> for clarifying the spec here, maybe. I do think the behavior is covered, as
> I outlined above. And as above, I'm not sure how to clarify it further,
> while still leaving up the space we want to left open.
>
>
> I vote for making this openness explicit, meaning that even the optimizer
> is free to make assumptions that do not hold during runtime. So if you have
> a pointer derived from something pointing to a zero-size type it can
> compare with different results over time, even false when having the same
> value. I do not believe that is what’s currently in the spec.
>

> Cheers
> Oliver
>
>

-- 
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/CAEkBMfGOWoQYrQ9qm_9%2BdyvEObJV3JP%2BhwwFj9%2Bgo%3DqusRVL7A%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Oliver Eikemeier

> Am 20.06.2024 um 13:24 schrieb Axel Wagner :
> 
> We can see that 1. `unsafe.Pointer` is definitionally a pointer type, 2. in 
> your example, the two `unsafe.Pointers` do not point to the same variable and 
> do not have the value `nil` and 3. are not pointing at distinct zero-sized 
> variables. So their comparison should be `false`, which is what your example 
> observes.

Does it (Go Playground )?

func f5() {
var (
a  struct{}
b  int
aa = (*int)(unsafe.Pointer())
ba = (*int)(unsafe.Pointer())
eq = aa == ba
)

println(":", aa, reflect.TypeOf(aa).String())
println(":", ba, reflect.TypeOf(ba).String())
println(" == :", eq)
cmpIntPtr(aa, ba)
}

func cmpIntPtr(p1 *int, p2 *int) {
fmt.Println("p1 == p2:", p1 == p2)
}

: 0xc466f8 *int
: 0xc466f8 *int
 == : false
p1 == p2: true


> All of this would be fine. What makes your example confusing is that you use 
> `println` to output them and see that they "have the same value".

Not really. I use println to not let them escape (which would change results, 
obviously) and only print out the pointer values to show that we can construct 
some piece of code that sees them as identical, see above.

> Note that if you *don't* convert an `unsafe.Pointer` to `uintptr`, you have 
> no way to argue that they "are actually equal"

I can by doing something like

*aa = 42
fmt.Println(aa == ba, *ba)

“Two pointer values are equal if they point to the same variable” - aa and ba 
do. Note that “A variable is a storage location for holding a value.”

>> I’m advocating for at least a FAQ article,
> 
> I tend to agree, though I'm not sure how to phrase that, beyond saying "do 
> not make any assumptions about the identity pointers to zero-sized variables 
> or with zero-sized base types or that where derived from one of those" and 
> I'm not sure how helpful that is.

It seems like a frequently asked question to me ;)

>> but also think the specification should be adapted, for clarity but also for 
>> the fact that only one pointer pointing to a zero-sized variable can compare 
>> differently to anything over time, even things having the same address value.
> 
> Note that "address value" is not something that exists within the spec. As 
> for clarifying the spec here, maybe. I do think the behavior is covered, as I 
> outlined above. And as above, I'm not sure how to clarify it further, while 
> still leaving up the space we want to left open.

I vote for making this openness explicit, meaning that even the optimizer is 
free to make assumptions that do not hold during runtime. So if you have a 
pointer derived from something pointing to a zero-size type it can compare with 
different results over time, even false when having the same value. I do not 
believe that is what’s currently in the spec.

Cheers
Oliver

-- 
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/AEB06A98-1372-4478-BBEB-514B617852A2%40fillmore-labs.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Jan Mercl
On Thu, Jun 20, 2024 at 1:26 PM 'Axel Wagner' via golang-nuts
 wrote:

> (apologies for the abundance of grammatical and spelling errors that occurred 
> during editing and of course only became visible after hitting "send")

(Send collapses the wave function  ;-)

-- 
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/CAA40n-VMr0y%3D842etNGux4Xubc6B3dkhHxxrWtpSocpJsGxBfg%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread 'Axel Wagner' via golang-nuts
(apologies for the abundance of grammatical and spelling errors that
occurred during editing and of course only became visible after hitting
"send")

On Thu, 20 Jun 2024 at 13:24, Axel Wagner 
wrote:

> On Thu, 20 Jun 2024 at 12:28, Oliver Eikemeier <
> eikeme...@fillmore-labs.com> wrote:
>
>> Let me start with this: I’m fine with the behavior, it is exotic enough
>> that even the optimizer should be allowed to assume something that doesn’t
>> hold during runtime, since it simplifies things.
>>
>> What I think is at least surprising and at worst lacking is the
>> documentation.
>>
>> It mentions “pointers” (plural) to zero-sized variables, but for this
>> behavior it is sufficient when only one pointer derives from a pointer to a
>> zero-sized variable, as demonstrated in the example below.
>>
>
> Re-visiting your example, it is indeed interesting that I realized before.
> I'll note that you need to involve `unsafe.Pointer` to observe this, as you
> may not compare pointers to different types. And `unsafe.Pointer`'s
> behaviors are somewhat left up to the implementation.
>
> The spec ays: 
>
> A Pointer is a pointer type  but a
>> Pointer value may not be dereferenced
>> . Any pointer or value of core
>> type  uintptr can be converted
>>  to a type of core type Pointer and
>> vice versa. The effect of converting between Pointer and uintptr is
>> implementation-defined.
>
>
> The thing that stands out is that it leaves the effect of converting to
> `uintptr` up to the implementation, but nothing else. So any other rule, as
> far as the language is concerned, should be derived from the rules for
> pointer types (except that they can not be dereferenced).
>
> One contradiction here is that this section references the definition of a
> pointer type, which says
>
> A pointer type denotes the set of all pointers to variables
>>  of a given type, called the *base
>> type* of the pointer.
>>
>
> This contradicts the nature of `unsafe.Pointer`, though, which does not
> have a base type. That difference is what causes the trouble: When the spec
> defines pointer comparisons by
>
> Pointer types are comparable. Two pointer values are equal if they point
>> to the same variable or if both have value nil. Pointers to distinct
>> zero-size 
>> variables may or may not be equal.
>
>
> We can see that 1. `unsafe.Pointer` is definitionally a pointer type, 2.
> in your example, the two `unsafe.Pointers` do not point to the same
> variable and do not have the value `nil` and 3. are not pointing at
> distinct zero-sized variables. So their comparison should be `false`, which
> is what your example observes.
>
> All of this would be fine. What makes your example confusing is that you
> use `println` to output them and see that they "have the same value". For
> that, we need to look at the definition of `println`
> :
>
> Current implementations provide several built-in functions useful during
>> bootstrapping. These functions are documented for completeness but are not
>> guaranteed to stay in the language. They do not return a result.
>>
>> Function   Behavior
>>
>> print  prints all arguments; formatting of arguments is 
>> implementation-specific
>> printlnlike print but prints spaces between arguments and a newline at 
>> the end
>>
>> Implementation restriction: print and println need not accept arbitrary
>> argument types, but printing of boolean, numeric, and string types
>>  must be supported.
>>
> Notably, this says nothing about what happens if you pass a pointer type.
> That is thus left up to the implementation. In effect, it does the same as
> `fmt.Println` ultimately: It converts the pointer to `uintptr`, which as
> we've seen above is left to the implementation.
>
> Note that if you *don't* convert an `unsafe.Pointer` to `uintptr`, you
> have no way to argue that they "are actually equal". And if you don't use
> `unsafe.Pointer` you have no way to compare pointers to variables of
> different types. So, the only way to observe that behavior is to enter what
> is implementation-defined.
>
> So, yes. Your example is interesting, but still within spec.
>
> I’m advocating for at least a FAQ article,
>>
>
> I tend to agree, though I'm not sure how to phrase that, beyond saying "do
> not make any assumptions about the identity pointers to zero-sized
> variables or with zero-sized base types or that where derived from one of
> those" and I'm not sure how helpful that is.
>
>
>> but also think the specification should be adapted, for clarity but also
>> for the fact that only one pointer pointing to a zero-sized variable can
>> compare differently to anything over 

Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Jan Mercl
On Thu, Jun 20, 2024 at 1:16 PM Oliver Eikemeier
 wrote:

> • Pointer types are comparable. Two pointer values are equal if they point to 
> the same variable or if both have value nil. Pointers to distinct zero-size 
> variables may or may not be equal.

Compare to (made up) "NaNs always compare non-equal". It talks both
about '3.14 == NaN' and 'NaN == NaN'. The plural in our context means
"any, all and every". It does not specify only the last case of two
NaNs.

My 2c.

-- 
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/CAA40n-W%3D9EX5BFgVWibHF1nz5xDgX3Z3v6ptyD%2BeSwJLeBtSEg%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread 'Axel Wagner' via golang-nuts
On Thu, 20 Jun 2024 at 12:28, Oliver Eikemeier 
wrote:

> Let me start with this: I’m fine with the behavior, it is exotic enough
> that even the optimizer should be allowed to assume something that doesn’t
> hold during runtime, since it simplifies things.
>
> What I think is at least surprising and at worst lacking is the
> documentation.
>
> It mentions “pointers” (plural) to zero-sized variables, but for this
> behavior it is sufficient when only one pointer derives from a pointer to a
> zero-sized variable, as demonstrated in the example below.
>

Re-visiting your example, it is indeed interesting that I realized before.
I'll note that you need to involve `unsafe.Pointer` to observe this, as you
may not compare pointers to different types. And `unsafe.Pointer`'s
behaviors are somewhat left up to the implementation.

The spec ays: 

A Pointer is a pointer type  but a
> Pointer value may not be dereferenced
> . Any pointer or value of core
> type  uintptr can be converted
>  to a type of core type Pointer and
> vice versa. The effect of converting between Pointer and uintptr is
> implementation-defined.


The thing that stands out is that it leaves the effect of converting to
`uintptr` up to the implementation, but nothing else. So any other rule, as
far as the language is concerned, should be derived from the rules for
pointer types (except that they can not be dereferenced).

One contradiction here is that this section references the definition of a
pointer type, which says

A pointer type denotes the set of all pointers to variables
>  of a given type, called the *base
> type* of the pointer.
>

This contradicts the nature of `unsafe.Pointer`, though, which does not
have a base type. That difference is what causes the trouble: When the spec
defines pointer comparisons by

Pointer types are comparable. Two pointer values are equal if they point to
> the same variable or if both have value nil. Pointers to distinct
> zero-size 
> variables may or may not be equal.


We can see that 1. `unsafe.Pointer` is definitionally a pointer type, 2. in
your example, the two `unsafe.Pointers` do not point to the same variable
and do not have the value `nil` and 3. are not pointing at distinct
zero-sized variables. So their comparison should be `false`, which is what
your example observes.

All of this would be fine. What makes your example confusing is that you
use `println` to output them and see that they "have the same value". For
that, we need to look at the definition of `println`
:

Current implementations provide several built-in functions useful during
> bootstrapping. These functions are documented for completeness but are not
> guaranteed to stay in the language. They do not return a result.
>
> Function   Behavior
>
> print  prints all arguments; formatting of arguments is 
> implementation-specific
> printlnlike print but prints spaces between arguments and a newline at 
> the end
>
> Implementation restriction: print and println need not accept arbitrary
> argument types, but printing of boolean, numeric, and string types
>  must be supported.
>
Notably, this says nothing about what happens if you pass a pointer type.
That is thus left up to the implementation. In effect, it does the same as
`fmt.Println` ultimately: It converts the pointer to `uintptr`, which as
we've seen above is left to the implementation.

Note that if you *don't* convert an `unsafe.Pointer` to `uintptr`, you have
no way to argue that they "are actually equal". And if you don't use
`unsafe.Pointer` you have no way to compare pointers to variables of
different types. So, the only way to observe that behavior is to enter what
is implementation-defined.

So, yes. Your example is interesting, but still within spec.

I’m advocating for at least a FAQ article,
>

I tend to agree, though I'm not sure how to phrase that, beyond saying "do
not make any assumptions about the identity pointers to zero-sized
variables or with zero-sized base types or that where derived from one of
those" and I'm not sure how helpful that is.


> but also think the specification should be adapted, for clarity but also
> for the fact that only one pointer pointing to a zero-sized variable can
> compare differently to anything over time, even things having the same
> address value.
>

Note that "address value" is not something that exists within the spec. As
for clarifying the spec here, maybe. I do think the behavior is covered, as
I outlined above. And as above, I'm not sure how to clarify it further,
while still leaving up the space we want to left open.


>
> I do not believe the specification is 

Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Oliver Eikemeier
https://go.dev/ref/spec#Comparison_operators

• Pointer types are comparable. Two pointer values are equal if they point 
to the same variable or if both have value nil. Pointers to distinct zero-size 
variables may or may not be equal.

Another example (Go Playground ):

func f4() {
var (
a  struct{}
b  int
aa = (*int)(unsafe.Pointer())
ba = (*int)(unsafe.Pointer())
eq = aa == ba
)

println(":", aa, reflect.TypeOf(aa).String())
println(":", ba, reflect.TypeOf(ba).String())
println(" == :", eq)
}

: 0xc466f8 *int
: 0xc466f8 *int
 == : false

We do not have “pointers to distinct zero-size variables”, only one pointer 
derived from a pointer to a zero-sized variable.

I don’t want to be stubborn. What would be the issue with at least adding a FAQ 
entry? I could open a PR suggesting something, although I’m not a native 
speaker and might not exactly hit the tone of the document.

> Am 20.06.2024 um 12:37 schrieb Jan Mercl <0xj...@gmail.com>:
> 
> On Thu, Jun 20, 2024 at 12:28 PM Oliver Eikemeier
>  wrote:
> 
>> It mentions “pointers” (plural) to zero-sized variables, but for this 
>> behavior it is sufficient when only one pointer derives from a pointer to a 
>> zero-sized variable, as demonstrated in the example below.
> 
> The plural is there because the specification discusses all such
> pointers, not a particular case.
> 
> The wording is IMO correct and clear. All/any pointers (plural) to
> zero sized objects may produce any/unpredictable result in comparison
> operations. Relying on the outcome is a bug, because the specs
> explicitly say otherwise.

-- 
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/C02D6616-0B77-4F6F-8597-EFA355BF17E1%40fillmore-labs.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Jan Mercl
On Thu, Jun 20, 2024 at 12:28 PM Oliver Eikemeier
 wrote:

> It mentions “pointers” (plural) to zero-sized variables, but for this 
> behavior it is sufficient when only one pointer derives from a pointer to a 
> zero-sized variable, as demonstrated in the example below.

The plural is there because the specification discusses all such
pointers, not a particular case.

The wording is IMO correct and clear. All/any pointers (plural) to
zero sized objects may produce any/unpredictable result in comparison
operations. Relying on the outcome is a bug, because the specs
explicitly say otherwise.

-- 
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/CAA40n-W8sYn56qRwX9ijEe9eK5bBxKCf_M2tX4_pxPMrWgi2hQ%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-20 Thread Oliver Eikemeier
Let me start with this: I’m fine with the behavior, it is exotic enough that 
even the optimizer should be allowed to assume something that doesn’t hold 
during runtime, since it simplifies things.

What I think is at least surprising and at worst lacking is the documentation.

It mentions “pointers” (plural) to zero-sized variables, but for this behavior 
it is sufficient when only one pointer derives from a pointer to a zero-sized 
variable, as demonstrated in the example below.

I’m advocating for at least a FAQ article, but also think the specification 
should be adapted, for clarity but also for the fact that only one pointer 
pointing to a zero-sized variable can compare differently to anything over 
time, even things having the same address value.

I do not believe the specification is clear on this. Otherwise I don’t think 
this is urgent. But it seems to pop up repeatedly.

Cheers
Oliver

> Am 19.06.2024 um 23:16 schrieb 'Axel Wagner' via golang-nuts 
> :
> 
> The spec says both. It says
>> Two distinct zero-size variables may have the same address in memory.
> And it says
>> Pointers to distinct zero-size variables may or may not be equal.
> 
> The former means what you say. The latter means what Ian says.
> 
>> Then I have two pointers. Where in the spec is “the result of comparison of 
>> pointers may change over time”?
>>  
>> For example (Go Playground ):
>> 
>> func f3() {
>>  var (
>>  a  struct{}
>>  b  int
>>  aa = unsafe.Pointer()
>>  ba = unsafe.Pointer()
>>  eq = aa == ba
>>  )
>> 
>>  println(":", aa)
>>  println(":", ba)
>>  println(" == :", eq)
>> }
>> 
>> gives
>> 
>> : 0xc46738
>> : 0xc46738
>>  == : false 
>> 
>> and  is not even a pointer to a zero-sized variable.

-- 
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/60900D25-852D-4A9F-904F-D2ECFF47576D%40fillmore-labs.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-19 Thread 'Axel Wagner' via golang-nuts
On Wed, 19 Jun 2024 at 22:43, Oliver Eikemeier  wrote:

> The specs says, as you say above, "Pointers to distinct zero-size
> variables may or may not be equal.” That means that you can't predict
> the result of any given comparison of addresses of zero-sized
> variables.
>
>
> I'm not sure I read it that way. I would interpret it as *“taking pointer
> to distinct zero-size variables may or may not result in equal pointers”*.
>
> But not being able to have a *repeatable* result of a pointer comparison
> seems strange to me. The specification says “you'll get *some* pointers”.
> Fine.
>

The spec says both. It says

> Two distinct zero-size variables may have the same address in memory.

And it says

> Pointers to distinct zero-size variables may or may not be equal.


The former means what you say. The latter means what Ian says.

Then I have two pointers. Where in the spec is “the result of comparison of
> pointers may change over time”?
>

> For example (Go Playground ):
>
> func f3() {
> var (
> a  struct{}
> b  int
> aa = unsafe.Pointer()
> ba = unsafe.Pointer()
> eq = aa == ba
> )
>
> println(":", aa)
> println(":", ba)
> println(" == :", eq)
> }
>
> gives
>
> : 0xc46738
> : 0xc46738
>  == : false
>
> and  is not even a pointer to a zero-sized variable.
>
> Could be true, could be false, could change each time you
> do the comparison. So this behavior is permitted by the spec.
>
>
> I'm not sure about the “undefined behavior *over time*”. I get that the
> compiler lays out the memory however it sees fit, but then I should have
> unchanging values in my variables.
>
>
> > The interesting part here is that I can create two pointers (which may
> or may not be equal per specification), but depending on how I compare them
> I get different results.
>
> Yes, as the spec permits.
>
>
>  I assume this has little relevance in practice, but it is surprising.
>
> --
> 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/64e58302-59a6-4cbf-859e-aa6b8a2b6068n%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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfE6bzYQJ7s_GHEN7%3Dp3s2p0pSWNMgcw8t4tTiSy04ucFg%40mail.gmail.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-19 Thread Oliver Eikemeier

Hi,

Ian Lance Taylor schrieb am Mittwoch, 19. Juni 2024 um 19:19:09 UTC+2:

On Wed, Jun 19, 2024 at 9:59 AM Oliver Eikemeier  
wrote: 
> The specification says: “Pointers to distinct zero-size variables may or 
may not be equal.” 

The specs says, as you say above, "Pointers to distinct zero-size 
variables may or may not be equal.” That means that you can't predict 
the result of any given comparison of addresses of zero-sized 
variables.


I'm not sure I read it that way. I would interpret it as *“taking pointer 
to distinct zero-size variables may or may not result in equal pointers”*.

But not being able to have a *repeatable* result of a pointer comparison 
seems strange to me. The specification says “you'll get *some* pointers”. 
Fine.

Then I have two pointers. Where in the spec is “the result of comparison of 
pointers may change over time”?
 
For example (Go Playground ):

func f3() {
var (
a  struct{}
b  int
aa = unsafe.Pointer()
ba = unsafe.Pointer()
eq = aa == ba
)

println(":", aa)
println(":", ba)
println(" == :", eq)
}

gives

: 0xc46738
: 0xc46738
 == : false 

and  is not even a pointer to a zero-sized variable.

Could be true, could be false, could change each time you 
do the comparison. So this behavior is permitted by the spec. 


I'm not sure about the “undefined behavior *over time*”. I get that the 
compiler lays out the memory however it sees fit, but then I should have 
unchanging values in my variables.
 

> The interesting part here is that I can create two pointers (which may or 
may not be equal per specification), but depending on how I compare them I 
get different results. 

Yes, as the spec permits. 


 I assume this has little relevance in practice, but it is surprising.

-- 
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/64e58302-59a6-4cbf-859e-aa6b8a2b6068n%40googlegroups.com.


Re: [go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-19 Thread Ian Lance Taylor
On Wed, Jun 19, 2024 at 9:59 AM Oliver Eikemeier
 wrote:
>
> I'm observing some strange behavior and could use some help understanding it.
>
> The specification says: “Pointers to distinct zero-size variables may or may 
> not be equal.”
>
> With the following program (Go Playground):
>
> var ( a struct{} b struct{} eq =  ==  ) func f1() { println(":", ) 
> println(":", ) println(" == :", eq) }
>
>
> I'll get
>
> : 0x537580 : 0x537580  == : false
>
>
> Okay, a and b are empty structs, do not escape, so they share the same 
> address - fine. Also, some optimizer sees that a and b are different 
> variables, so their addresses must be different, and decides to make  ==  
> a constant - wrong, but I can live with that.
>
> My question would be: Is this behavior expected, somehow defined by the 
> specification, or is it undefined behavior?

The specs says, as you say above, "Pointers to distinct zero-size
variables may or may not be equal.”  That means that you can't predict
the result of any given comparison of addresses of zero-sized
variables.  Could be true, could be false, could change each time you
do the comparison.  So this behavior is permitted by the spec.



> Let's try to confuse the optimizer a little (Go Playground):
>
> var ( a struct{} b struct{} aa =  ba =  eq = aa == ba ) func f1() { 
> println(":", aa) println(":", ba) println(" == :", eq) }
>
> results in
>
> : 0x5375a0 : 0x5375a0  == : true
>
>
> Mission accomplished, too complicated to calculate in advance. But globals 
> are bad, so (Go Playground):
>
> func f2() { var ( a struct{} b struct{} aa =  ba =  eq = aa == ba ) 
> println(":", aa) println(":", ba) println(" == :", eq) }
>
> : 0xc46740 : 0xc46740  == : false
>
>
> Seems like inlining helps generate false answers.
>
> The interesting part here is that I can create two pointers (which may or may 
> not be equal per specification), but depending on how I compare them I get 
> different results.

Yes, as the spec permits.

Ian

-- 
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/CAOyqgcXRr24VJNsbv_-b4HS6XGVBgKcTv5Ny4rsMvHFuMPvkvQ%40mail.gmail.com.


[go-nuts] Comparison of pointers to distinct zero-sized variables

2024-06-19 Thread Oliver Eikemeier


I'm observing some strange behavior and could use some help understanding 
it.

The specification 
 says: *“Pointers to distinct zero-size variables may or may not be equal.”*

With the following program (Go Playground 
):
var ( a struct{} b struct{} eq =  ==  ) func f1() { println(":", ) 
println(":", ) println(" == :", eq) } 


I'll get
: 0x537580 : 0x537580  == : false 


Okay, a and b are empty structs, do not escape, so they share the same 
address - fine. Also, some optimizer sees that a and b are different 
variables, so their addresses must be different, and decides to make  == 
 a constant - wrong, but I can live with that.

My question would be: Is this behavior expected, somehow defined by the 
specification, or is it undefined behavior?

Let's try to confuse the optimizer a little (Go Playground 
):
var ( a struct{} b struct{} aa =  ba =  eq = aa == ba ) func f1() { 
println(":", aa) println(":", ba) println(" == :", eq) } 

results in
: 0x5375a0 : 0x5375a0  == : true 


Mission accomplished, too complicated to calculate in advance. But globals 
are bad, so (Go Playground ):
func f2() { var ( a struct{} b struct{} aa =  ba =  eq = aa == ba ) 
println(":", aa) println(":", ba) println(" == :", eq) } 

: 0xc46740 : 0xc46740  == : false 


Seems like inlining helps generate false answers.

The interesting part here is that I can create two pointers (which may or 
may not be equal per specification), but depending on how I compare them I 
get different results.

-- 
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/9dc278ed-d138-4adc-bf68-787bdc8cb71cn%40googlegroups.com.