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 <axel.wagner...@googlemail.com> 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.
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.
func f5() { var ( a struct{} b int aa = (*int)(unsafe.Pointer(&a)) ba = (*int)(unsafe.Pointer(&b)) eq = aa == ba )
println("&a:", aa, reflect.TypeOf(aa).String()) println("&b:", ba, reflect.TypeOf(ba).String()) println("&a == &b:", eq) cmpIntPtr(aa, ba) }
func cmpIntPtr(p1 *int, p2 *int) { fmt.Println("p1 == p2:", p1 == p2) }
&a: 0xc0000466f8 *int
&b: 0xc0000466f8 *int
&a == &b: false
p1 == 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.
--
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 discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/D6910B1E-3650-4356-97E3-37E8C1853EA1%40ix.netcom.com.
|