collections: Don't panic when Has called on uninitialized Set

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.
pull/35031/head
Martin Atkins 2 years ago
parent b718c55b13
commit ef185ee6a0

@ -49,6 +49,11 @@ func NewSetCmp[T comparable]() Set[T] {
// Has returns true if the given value is present in the set, or false
// otherwise.
func (s Set[T]) Has(v T) bool {
if len(s.members) == 0 {
// We'll skip calling "s.key" in this case, so that we don't panic
// if called on an uninitialized Set.
return false
}
k := s.key(v)
_, ok := s.members[k]
return ok

@ -37,3 +37,17 @@ func TestSet(t *testing.T) {
t.Errorf("set doesn't have \"b\" after adding it")
}
}
func TestSetUninit(t *testing.T) {
// An zero-value set should behave like it's empty for read-only operations.
var zeroSet Set[string]
if got, want := zeroSet.Len(), 0; got != want {
t.Errorf("wrong number of elements\ngot: %d\nwant: %d", got, want)
}
if zeroSet.Has("anything") {
// (this is really just testing that we can call Has without panicking;
// it's unlikely that this would ever fail by successfully lying about
// a particular member being present.)
t.Error("Has reported that \"anything\" is present")
}
}

Loading…
Cancel
Save