// Copyright IBM Corp. 2014, 2026 // SPDX-License-Identifier: BUSL-1.1 package collections // UniqueKey represents a value that is comparable and uniquely identifies // another value of type T. // // The Go type system offers no way to guarantee at compile time that // implementations of this type are comparable, but if this interface is // implemented by an uncomparable type then that will cause runtime panics // when inserting elements into collection types that use unique keys. // // We use this to help with correctness of the unique-key-generator callbacks // used with the collection types in this package, so help with type parameter // inference and to raise compile-time errors if an inappropriate callback // is used as the key generator for a particular collection. type UniqueKey[T any] interface { // Implementations must include an IsUniqueKey method with an empty body // just as a compile-time assertion that they are intended to behave as // unique keys for a particular other type. // // This method is never actually called by the collection types. Other // callers could potentially call it, but it would be strange and pointless // to do so. IsUniqueKey(T) } // A UniqueKeyer is a type that knows how to calculate a unique key itself. type UniqueKeyer[T any] interface { // UniqueKey returns the unique key of the reciever. // // A correct implementation of UniqueKey must return a distinct value // for each unique value of T, where the uniqueness of T values is decided // by the implementer. See [UniqueKey] for more information. // // Although not enforced directly by the Go type system, it doesn't make // sense for a type to implement [UniqueKeyer] for any type other than // itself. Such a nonsensical implementation will not be accepted by // functions like [NewSet] and [NewMap]. UniqueKey() UniqueKey[T] } // cmpUniqueKey is an annoying little adapter used to make arbitrary // comparable types usable with [Set] and [Map]. // // It just wraps a single-element array of T around the value, so it // remains exactly as comparable as T. However, it does unfortunately // mean redundantly storing T twice -- both as the unique key and the // value -- in our collections. type cmpUniqueKey[T comparable] [1]T func (cmpUniqueKey[T]) IsUniqueKey(T) {} func cmpUniqueKeyFunc[T comparable](v T) UniqueKey[T] { return cmpUniqueKey[T]{v} }