The convention for Go maps is that read operations treat an uninitialized
map as if empty, and collections.Set is intended to behave in a map-like
way, so Set.Has should return false when called on a totally-uninitialized
set.
Previously this would panic because an uninitialized set has a nil key
function.
A downside of using custom collection types is that go-cmp doesn't support
them automatically, and so we need to help it out a little by providing
additional options.
An additional awkwardness is that go-cmp does all of its work at runtime
using reflection, at which point the generic types have all been erased
and lowered to many separate concrete types. Therefore we need some helper
functions to produce a dynamically representation using interface types,
cautiously exposing some internal details of these types only for go-cmp's
use.
The dynamic adapter here unfortunately means that the compiler likely
won't be able to optimize away CmpOptions in non-test builds, but we'll
accept that for now since the cost of that inert data and code is
relatively small. If it turns out to be a problem then we'll need to find
a different strategy, but hopefully not.
Similar to the built-in map types in Go, the zero value of collections.Map
now behaves as if empty on read, and generates actionable panics when
attempting to write.
This is a generalization of the similar types previously implemented in
package addrs, now available for a type in any package as long as we can
write a suitable rule for calculating a unique key for each distinct value
of that type.
Hopefully these eventually get replaced by future Go standard library
functions, but this is here to fill that gap for us in the meantime.