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

Comparer doesn't run when type is wrapped in empty interface #361

Closed
danielchatfield opened this issue Jul 25, 2024 · 3 comments
Closed

Comments

@danielchatfield
Copy link

Consider the following example:

type I interface {
     V() string
}

type foo struct{
    v string
}

func(f foo) V() string {
     return f.v
}

type bar struct{
    v string
}

func(b bar) V() string {
     return b.v
}

var a,b I
a = foo{"test"}
b = bar{"test"}

cmp.Equal(a,b, cmp.Comparer(func(a, b I) {
     return a.V() == b.V()
})

Expectation: the comparer will be used to determine equality.

Reality: because a and b are different types they get wrapped in an empty interface which then fails the "can it be assigned to this interface" test and the comparer never gets invoked.

@danielchatfield
Copy link
Author

The documentation makes it clear this should work:

If T is an interface, it is possible that f is called with two values of different concrete types that both implement T.

@dsnet
Copy link
Collaborator

dsnet commented Jul 25, 2024

This is an unfortunate quirk of Go. The problem here is similar to how:

var a I
reflect.TypeOf(a) // reports `nil` rather than `I`

Go generics somewhat fixes this since you can now do:

reflect.TypeFor[I]() // properly reports `I`

However, the cmp package has not been updated to use generics.

As a work around you can do:

cmp.Equal(&a, &b, ...)

where you pass in pointers to the interface, which will ensure that the interface wrapping at the top-level does not get lost.

@dsnet
Copy link
Collaborator

dsnet commented Sep 27, 2024

Closing as inactionable. This is a quirk of the Go language.

@dsnet dsnet closed this as completed Sep 27, 2024
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