Skip to content

spec: when do struct comparisons panic? #38676

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

Closed
bradfitz opened this issue Apr 26, 2020 · 6 comments
Closed

spec: when do struct comparisons panic? #38676

bradfitz opened this issue Apr 26, 2020 · 6 comments

Comments

@bradfitz
Copy link
Contributor

bradfitz commented Apr 26, 2020

Should the spec clarify when a struct comparison panics?

e.g.

https://play.golang.org/p/4NUu89RI27t

package main

import "fmt"

func cmp(a, b S) {
	defer func() {
		if recover() != nil {
			fmt.Println("panic")
		}
	}()
	if a == b {
		fmt.Println("equal")
	} else {
		fmt.Println("not-equal")
	}
}

type S struct{ a, b interface{} }

func main() {
	var f func()
	cmp(S{1, f}, S{2, f})
	cmp(S{f, 1}, S{f, 2})
}

Is it okay for implementations to have different answers to those two prints?

(Background: https://go-review.googlesource.com/c/go/+/230207, cmd/compile: improve generated eq algs for structs containing interfaces from @josharian)

/cc @griesemer @ianlancetaylor @mdempsky

@josharian
Copy link
Contributor

I believe the relevant part of the spec is:

A comparison of two interface values with identical dynamic types causes a run-time panic if values of that type are not comparable. This behavior applies not only to direct interface value comparisons but also when comparing arrays of interface values or structs with interface-valued fields.

A very literal reading of the spec suggests Brad’s program should print “panic, panic”. Currently it prints “not-equal, panic”. The CL Brad linked to would not change the output for this particular program, but for similar programs, it might change the output to “not-equal, not-equal”.

@randall77
Copy link
Contributor

It would be unfortunate if, when comparing [100]interface{}, we had to compare all 100 entries even when the first entry reports !=.
Not the end of the world, though.

@mdempsky
Copy link
Contributor

I think this is #8606

@bradfitz
Copy link
Contributor Author

@mdempsky, thanks! Closing this one as a duplicate.

@zigo101
Copy link

zigo101 commented Apr 27, 2020

If both of the filed names are changed to _, then the comparisons results are equal. Bug?

package main

import "fmt"

func cmp(a, b S) {
	defer func() {
		if recover() != nil {
			fmt.Println("panic")
		}
	}()
	if a == b {
		fmt.Println("equal")
	} else {
		fmt.Println("not-equal")
	}
}

type S struct{_, _ interface{} }

func main() {
	var f func()
	cmp(S{1, f}, S{2, f}) // equal
	cmp(S{f, 1}, S{f, 2}) // equal
}

@mdempsky
Copy link
Contributor

https://golang.org/ref/spec#Comparison_operators:

"Two struct values are equal if their corresponding non-blank fields are equal."

@golang golang locked and limited conversation to collaborators Apr 27, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants