type Map … type entry … // SetHasher sets the hasher used by Map. // // All Hashers are functionally equivalent but contain internal state // used to cache the results of hashing previously seen types. // // A single Hasher created by MakeHasher() may be shared among many // Maps. This is recommended if the instances have many keys in // common, as it will amortize the cost of hash computation. // // A Hasher may grow without bound as new types are seen. Even when a // type is deleted from the map, the Hasher never shrinks, since other // types in the map may reference the deleted type indirectly. // // Hashers are not thread-safe, and read-only operations such as // Map.Lookup require updates to the hasher, so a full Mutex lock (not a // read-lock) is require around all Map operations if a shared // hasher is accessed from multiple threads. // // If SetHasher is not called, the Map will create a private hasher at // the first call to Insert. func (m *Map) SetHasher(hasher Hasher) { … } // Delete removes the entry with the given key, if any. // It returns true if the entry was found. func (m *Map) Delete(key types.Type) bool { … } // At returns the map entry for the given key. // The result is nil if the entry is not present. func (m *Map) At(key types.Type) any { … } // Set sets the map entry for key to val, // and returns the previous entry, if any. func (m *Map) Set(key types.Type, value any) (prev any) { … } // Len returns the number of map entries. func (m *Map) Len() int { … } // Iterate calls function f on each entry in the map in unspecified order. // // If f should mutate the map, Iterate provides the same guarantees as // Go maps: if f deletes a map entry that Iterate has not yet reached, // f will not be invoked for it, but if f inserts a map entry that // Iterate has not yet reached, whether or not f will be invoked for // it is unspecified. func (m *Map) Iterate(f func(key types.Type, value any)) { … } // Keys returns a new slice containing the set of map keys. // The order is unspecified. func (m *Map) Keys() []types.Type { … } func (m *Map) toString(values bool) string { … } // String returns a string representation of the map's entries. // Values are printed using fmt.Sprintf("%v", v). // Order is unspecified. func (m *Map) String() string { … } // KeysString returns a string representation of the map's key set. // Order is unspecified. func (m *Map) KeysString() string { … } type Hasher … // MakeHasher returns a new Hasher instance. func MakeHasher() Hasher { … } // Hash computes a hash value for the given type t such that // Identical(t, t') => Hash(t) == Hash(t'). func (h Hasher) Hash(t types.Type) uint32 { … } // hashString computes the Fowler–Noll–Vo hash of s. func hashString(s string) uint32 { … } // hashFor computes the hash of t. func (h Hasher) hashFor(t types.Type) uint32 { … } func (h Hasher) hashTuple(tuple *types.Tuple) uint32 { … } func (h Hasher) hashUnion(t *types.Union) uint32 { … } func (h Hasher) hashTermSet(terms []*types.Term) uint32 { … } // hashTypeParam returns a hash of the type parameter t, with a hash value // depending on whether t is contained in h.sigTParams. // // If h.sigTParams is set and contains t, then we are in the process of hashing // a signature, and the hash value of t must depend only on t's index and // constraint: signatures are considered identical modulo type parameter // renaming. To avoid infinite recursion, we only hash the type parameter // index, and rely on types.Identical to handle signatures where constraints // are not identical. // // Otherwise the hash of t depends only on t's pointer identity. func (h Hasher) hashTypeParam(t *types.TypeParam) uint32 { … } // hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that // pointers values are not dependent on the GC. func (h Hasher) hashPtr(ptr any) uint32 { … } // shallowHash computes a hash of t without looking at any of its // element Types, to avoid potential anonymous cycles in the types of // interface methods. // // When an unnamed non-empty interface type appears anywhere among the // arguments or results of an interface method, there is a potential // for endless recursion. Consider: // // type X interface { m() []*interface { X } } // // The problem is that the Methods of the interface in m's result type // include m itself; there is no mention of the named type X that // might help us break the cycle. // (See comment in go/types.identical, case *Interface, for more.) func (h Hasher) shallowHash(t types.Type) uint32 { … }