In Go 1.18 and Go 1.19 I can ensure at compile time that a type is strictly comparable, i.e. it supports ==
and !=
operators and those are guaranteed to not panic at run time.
This is useful for example to avoid inadvertently adding fields to a struct that could cause unwanted panics.
I just attempt to instantiate comparable
with it:
// supports == and != but comparison could panic at run time
type Foo struct {
SomeField any
}
func ensureComparable[T comparable]() {
// no-op
}
var _ = ensureComparable[Foo] // doesn't compile because Foo comparison may panic
This is possible in Go 1.18 and 1.19 due to the very definition of the comparable
constraint:
The predeclared interface type comparable denotes the set of all non-interface types that are comparable
Even though the Go 1.18 and 1.19 spec fail to mention types that are not interfaces but also not strictly comparable, e.g. [2]fmt.Stringer
or struct { foo any }
, the gc compiler does reject these as arguments for comparable
.
Playground with several examples: https://go.dev/play/p/_Ggfdnn6OzZ
With Go 1.20, instantiating comparable
will be aligned with the broader notion of comparability. This makes ensureComparable[Foo]
compile even though I don't want it to.
Is there a way to statically ensure strict comparability with Go 1.20?
Foo
type(s)? – Crossquestion