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: Go 2: spec: always permit comparisons against zero value of type #26842

Open
jimmyfrasche opened this Issue Aug 7, 2018 · 3 comments

Comments

Projects
None yet
5 participants
@jimmyfrasche
Copy link
Member

jimmyfrasche commented Aug 7, 2018

Go, effectively, has three-kinds of comparability:

  • incomparable, there is no == operator defined for a type (structs and arrays with incomparable fields).
  • 0-comparable, there is an == operator but it can only test against the zero value (funcs, maps, and slices can be compared against nil). The spec treats these as incomparable types and notes the special case.
  • comparable, there is an == operator and it works for all values

When writing code with known types, this is not an issue. You know if there's an == operator and whether you can compare against all values or just the zero value.

When generating code (or, possibly in the future, writing generic code) over arbitrary types, this asymmetry is a bit more bothersome. You can't just classify types as comparable or incomparable, you need to handle the 0-comparable case as well even though it is so similar: https://play.golang.org/p/JOmxaVJoYtT

I propose collapsing incomparable and 0-comparable. Allow incomparable structs and arrays to be compared to their zero value. There would always be an == operator and it would always be safe to compare any value to zero. Care would still need to be taken to ensure comparability when using == between arbitrary values, but the simpler classification eases matters.

I believe this would be a 100% backwards-compatible change and perhaps even simplify the spec a bit (or at least not require too many changes).

The concerns would be go/types and reflect, but they both seem to lump what I call 0-comparability in with incomparability, but there, admittedly, could be subtler implications.

This is tangentially related to defining a universal zero value #19642 (comment) in that similar arguments are involved and the two would compliment each other.

@gopherbot gopherbot added this to the Proposal milestone Aug 7, 2018

@gopherbot gopherbot added the Proposal label Aug 7, 2018

@ianlancetaylor ianlancetaylor changed the title proposal: spec: Simplify comparability proposal: Go 2: spec: always permit comparisons against zero value of type Aug 7, 2018

@cherrymui

This comment has been minimized.

Copy link
Contributor

cherrymui commented Aug 8, 2018

Does the zero value need to be static? Or it can be dynamic, as long as at run time, at the point of ==, the value is zero?

From https://play.golang.org/p/JOmxaVJoYtT,

	// var zero t
	// fmt.Println(a == zero)

it seems to suggest that the zero value does not have to be static (it is a variable). What if the value is not zero, then? Panic?

@jimmyfrasche

This comment has been minimized.

Copy link
Member

jimmyfrasche commented Aug 8, 2018

One side would need to be known to be zero statically. Having a universal zero like in the linked issue would be the easiest way to achieve that.

@ndyakov

This comment has been minimized.

Copy link

ndyakov commented Nov 30, 2018

Let's look at time.Time.
There is a IsZero function that will show you if the time is empty or not. With your suggestion I think that there should be an interface for structs and only if the struct is implementing that interface it can be checked against zero. For example if you have:

t := time.Time{}
fmt.Println(t == zero) 

It should be transferred to something like

var t time.Time
fmt.Println(t.IsZero())

This is not the same as t == nil, although t == nil doesn't make sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment