Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

weak: docs don't guarantee Pointer compares not equal for different values #71381

Open
FiloSottile opened this issue Jan 22, 2025 · 6 comments
Open
Assignees
Labels
BugReport Issues describing a possible bug in the Go implementation. Documentation Issues describing a change to documentation. NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@FiloSottile
Copy link
Contributor

weak.Pointer docs say this about when they compare equal

// Two Pointer values always compare equal if the pointers from which they were
// created compare equal. This property is retained even after the
// object referenced by the pointer used to create a weak reference is
// reclaimed.
// If multiple weak pointers are made to different offsets within the same object
// (for example, pointers to different fields of the same struct), those pointers
// will not compare equal.
// If a weak pointer is created from an object that becomes unreachable, but is
// then resurrected due to a finalizer, that weak pointer will not compare equal
// with weak pointers created after the resurrection.

However, to use safely as a cache key, two things need to be true

  • always compare equal if the pointers from which they were created compare equal (yes)
  • never compare equal if the pointers from which they were created don't compare equal (unclear?)

In particular, I am worried about using weak.Make(x) as a cache key, then x is garbage collected, a new value y is allocated at the same address, and now weak.Make(y) compares equal to my weak.Pointer map key.

I think this can't be the case, because at that point Value would end up returning y instead of x, but that's me reading into the implementation details, rather than the docs telling me what I am doing is safe.

@gopherbot gopherbot added the Documentation Issues describing a change to documentation. label Jan 22, 2025
@gabyhelp gabyhelp added the BugReport Issues describing a possible bug in the Go implementation. label Jan 22, 2025
@ianlancetaylor
Copy link
Member

CC @mknyszek

@mknyszek
Copy link
Contributor

mknyszek commented Jan 22, 2025

What you intend to do is supported.

In particular, I am worried about using weak.Make(x) as a cache key, then x is garbage collected, a new value y is allocated at the same address, and now weak.Make(y) compares equal to my weak.Pointer map key.

This won't happen. Weak pointers map to object identity, not address identity, which "This property is retained even after the object referenced by the pointer used to create a weak reference is reclaimed" is trying to indicate.

I think the docs are a little confusing around "pointer" here, but mainly for those that understand what's going on under the hood. "Same pointer" doesn't really mean "same address." "Pointer" is being used in the sense of the Go spec, which isn't really aware of a garbage collector, and operates (in some sense) under an illusion of infinite memory (there's a way to create objects, but no way to destroy them).

To be absolutely clear: say you have a pointer to some object. If you copy that pointer and create two weak pointers from it, they will compare equal. If you lose that pointer and the object is collected, the two weak pointers will still compare equal. Later, if an object of the same type is allocated at the same address, weak pointers created to that object will not compare equal with the previous two weak pointers. At the point where the first object at that address is collected, you can never again construct a weak pointer that will compare equal to the two that pointed to that object, because you lost that object's pointer (even if other pointer values have the same address).

If you have suggestions on how to improve the docs, feel free to send a change, or post them here. Thanks.

@FiloSottile
Copy link
Contributor Author

Sweet, that's what I assumed but couldn't find definitive confirmation of in the docs.

I think it might be as simple as making the first sentence "Two Pointer values always compare equal if and only if the pointers from which they were created compare equal."

Does that sound correct?

@mknyszek
Copy link
Contributor

Yup, sounds right to me. I'll send a patch.

@mknyszek mknyszek self-assigned this Jan 23, 2025
@mknyszek mknyszek added this to the Go1.24 milestone Jan 23, 2025
@mknyszek mknyszek added the NeedsFix The path to resolution is known, but the work has not been done. label Jan 23, 2025
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/643935 mentions this issue: weak: clarify Pointer equality semantics

@gabyhelp
Copy link

Related Code Changes

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BugReport Issues describing a possible bug in the Go implementation. Documentation Issues describing a change to documentation. NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

5 participants