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

What is T in the documentation of Equal()? #364

Closed
your-diary opened this issue Sep 3, 2024 · 2 comments
Closed

What is T in the documentation of Equal()? #364

your-diary opened this issue Sep 3, 2024 · 2 comments

Comments

@your-diary
Copy link

If the values have an Equal method of the form "(T) Equal(T) bool" or "(T) Equal(I) bool" where T is assignable to I, then use the result of x.Equal(y) even if x or y is nil. Otherwise, no such method exists and evaluation proceeds to the next rule.

But T is not defined.

At first I thought T was the type of the compared values, but it turned out it wasn't.

For example, in the code below (playground), x.Equal(y) is called though the type of x is *U while there is NO method whose signature is (*U) Equal(*U) bool:

package main

import (
	"fmt"

	"github.com/google/go-cmp/cmp"
)

type S struct {
	V *U
}

type U struct {
}

//Note the signature is NOT `(*U) Equal(*U) bool` but `(U) Equal(U) bool`.
func (u1 U) Equal(u2 U) bool {
	fmt.Println("hello")
	return true
}

func main() {
	s1 := S{
		V: &U{},
	}
	s2 := S{
		V: &U{},
	}
	fmt.Println(cmp.Equal(s1, s2)) //=> hello, hello, true
}
@dsnet
Copy link
Collaborator

dsnet commented Sep 3, 2024

There's two issues being brough up in this issue.

Regarding documentation: The cmp package was written before the invention of Go generics, so it had to invent some form of notation to indicate generic code. The notation (T) Equal(T) was a primitive and custom way of verbally explaining generic code support. Notably, it doesn't really matter what T is, it's just some concrete Go type. The only thing of relevance is the relationship of T to I, which we explain in verbal prose.

Regarding behavior of Equal being called on *U and not just U, this is how methods work in Go in general, separate from the cmp package. For consistency, the cmp package is following the behavior of the Go language. For example, consider:

var err error = &MyError{}
type MyError struct{}
func (MyError) Error() string { return "" }

Note that *MyError implements the error interface even though the Error method is declared on MyError (and not *MyError). An implicit func (*MyError) Error() string implementation is produced by the Go language.

@your-diary
Copy link
Author

@dsnet
Thank you for your detailed explanation.
Now I understand the intention.

For consistency, the cmp package is following the behavior of the Go language.

I believe this should explicitly be noted in the documentation.
Actually I do know the rules you just described but was still confused.

But that is the matter of how the documentation uses natural languages and technical writings, which is out of the scope of this issue (e.g. maybe I should create a PR instead). Closing as solved...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants