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

proposal: unique: define Handle[T] zero value as handle to zero value of T #73344

Open
tylerchr opened this issue Apr 12, 2025 · 2 comments
Open
Labels
LanguageProposal Issues describing a requested change to the Go language specification. Proposal
Milestone

Comments

@tylerchr
Copy link

Proposal Details

I propose that the zero value of a unique.Handle[T] be explicitly defined as being a globally unique identity for the zero value of T. Specifically, I propose that:

  • unique.Make[T](T{}) should return the zero value of unique.Handle[T]
  • unique.Make[T]{}.Value() should return the zero value of T instead of panicking

This would have the effect of defining away the potential "invalid" state of a nil interior pointer.

Failing that, I propose that the documentation be updated to indicate that a zero value Handle is distinct from a Handle of the zero value, and clarify that it is potentially unsafe to use.

Motivation

The unique.Handle type is defined to be "a globally unique identity for some value of type T" and states that "Two handles compare equal exactly if the two values used to create the handles would have also compared equal." However, unique.Handle[T] actually has one more possible value than does T because it is possible for unique.Handle to be uninitialized.

This can create trouble when trying to intern a value of type T for types T with a useful zero value because it creates the potential for two distinct "zero" values: the zero value Handle[T] and the zero value T. At best, it is surprising to begin with a type T with a non-nil zero value and inadvertently introduce a hidden pointer after switching to unique.Handle[T]; at worst, it makes Value() potentially unsafe since it dereferences a hidden pointer. Issue #73266 makes reference to these difficulties.

Is there a strong use case for separating the two zero values that I am not aware of that justifies the sharp edge and makes it important that they be distinguishable?

Backwards Compatibility

I'm unsure whether this is a legal backwards-compatible change.

On one hand, the documentation of unique.Handle makes no mention of the behavior of its zero value. It also does not divulge that it has an interior pointer that can be nil and makes no reference to or commitments about invalid handles.

On the other hand, this would result in an observable behavioral change in programs. Consider:

invalid := unique.Handle[int]{}
zero := unique.Make(int(0))
fmt.Println(invalid == zero)
// Outputs "false" today, would change to "true" with this proposal

There is at least some precedent for making such potentially-observable behavior changes by leveraging the Forward Compatibility mechanism (#60078). I'm not familiar enough with it to know if that's an option here.

@gopherbot gopherbot added this to the Proposal milestone Apr 12, 2025
@gabyhelp
Copy link

@tylerchr tylerchr changed the title proposal: unique: Define Handle zero value as zero value of underlying type proposal: unique: Define Handle[T] zero value as zero value of T Apr 12, 2025
@tylerchr tylerchr changed the title proposal: unique: Define Handle[T] zero value as zero value of T proposal: unique: Define Handle[T] zero value as handle to zero value of T Apr 12, 2025
@gabyhelp gabyhelp added the LanguageProposal Issues describing a requested change to the Go language specification. label Apr 12, 2025
@prattmic
Copy link
Member

cc @golang/runtime @mknyszek

@seankhliao seankhliao changed the title proposal: unique: Define Handle[T] zero value as handle to zero value of T proposal: unique: define Handle[T] zero value as handle to zero value of T Apr 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LanguageProposal Issues describing a requested change to the Go language specification. Proposal
Projects
None yet
Development

No branches or pull requests

4 participants