1// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package typeutil defines various utilities for types, such as Map,
6// a mapping from types.Type to any values.
7package typeutil // import "golang.org/x/tools/go/types/typeutil"
8
9import (
10	"bytes"
11	"fmt"
12	"go/types"
13	"reflect"
14
15	"golang.org/x/tools/internal/aliases"
16	"golang.org/x/tools/internal/typeparams"
17)
18
19// Map is a hash-table-based mapping from types (types.Type) to
20// arbitrary any values.  The concrete types that implement
21// the Type interface are pointers.  Since they are not canonicalized,
22// == cannot be used to check for equivalence, and thus we cannot
23// simply use a Go map.
24//
25// Just as with map[K]V, a nil *Map is a valid empty map.
26//
27// Not thread-safe.
28type Map struct {
29	hasher Hasher             // shared by many Maps
30	table  map[uint32][]entry // maps hash to bucket; entry.key==nil means unused
31	length int                // number of map entries
32}
33
34// entry is an entry (key/value association) in a hash bucket.
35type entry struct {
36	key   types.Type
37	value any
38}
39
40// SetHasher sets the hasher used by Map.
41//
42// All Hashers are functionally equivalent but contain internal state
43// used to cache the results of hashing previously seen types.
44//
45// A single Hasher created by MakeHasher() may be shared among many
46// Maps.  This is recommended if the instances have many keys in
47// common, as it will amortize the cost of hash computation.
48//
49// A Hasher may grow without bound as new types are seen.  Even when a
50// type is deleted from the map, the Hasher never shrinks, since other
51// types in the map may reference the deleted type indirectly.
52//
53// Hashers are not thread-safe, and read-only operations such as
54// Map.Lookup require updates to the hasher, so a full Mutex lock (not a
55// read-lock) is require around all Map operations if a shared
56// hasher is accessed from multiple threads.
57//
58// If SetHasher is not called, the Map will create a private hasher at
59// the first call to Insert.
60func (m *Map) SetHasher(hasher Hasher) {
61	m.hasher = hasher
62}
63
64// Delete removes the entry with the given key, if any.
65// It returns true if the entry was found.
66func (m *Map) Delete(key types.Type) bool {
67	if m != nil && m.table != nil {
68		hash := m.hasher.Hash(key)
69		bucket := m.table[hash]
70		for i, e := range bucket {
71			if e.key != nil && types.Identical(key, e.key) {
72				// We can't compact the bucket as it
73				// would disturb iterators.
74				bucket[i] = entry{}
75				m.length--
76				return true
77			}
78		}
79	}
80	return false
81}
82
83// At returns the map entry for the given key.
84// The result is nil if the entry is not present.
85func (m *Map) At(key types.Type) any {
86	if m != nil && m.table != nil {
87		for _, e := range m.table[m.hasher.Hash(key)] {
88			if e.key != nil && types.Identical(key, e.key) {
89				return e.value
90			}
91		}
92	}
93	return nil
94}
95
96// Set sets the map entry for key to val,
97// and returns the previous entry, if any.
98func (m *Map) Set(key types.Type, value any) (prev any) {
99	if m.table != nil {
100		hash := m.hasher.Hash(key)
101		bucket := m.table[hash]
102		var hole *entry
103		for i, e := range bucket {
104			if e.key == nil {
105				hole = &bucket[i]
106			} else if types.Identical(key, e.key) {
107				prev = e.value
108				bucket[i].value = value
109				return
110			}
111		}
112
113		if hole != nil {
114			*hole = entry{key, value} // overwrite deleted entry
115		} else {
116			m.table[hash] = append(bucket, entry{key, value})
117		}
118	} else {
119		if m.hasher.memo == nil {
120			m.hasher = MakeHasher()
121		}
122		hash := m.hasher.Hash(key)
123		m.table = map[uint32][]entry{hash: {entry{key, value}}}
124	}
125
126	m.length++
127	return
128}
129
130// Len returns the number of map entries.
131func (m *Map) Len() int {
132	if m != nil {
133		return m.length
134	}
135	return 0
136}
137
138// Iterate calls function f on each entry in the map in unspecified order.
139//
140// If f should mutate the map, Iterate provides the same guarantees as
141// Go maps: if f deletes a map entry that Iterate has not yet reached,
142// f will not be invoked for it, but if f inserts a map entry that
143// Iterate has not yet reached, whether or not f will be invoked for
144// it is unspecified.
145func (m *Map) Iterate(f func(key types.Type, value any)) {
146	if m != nil {
147		for _, bucket := range m.table {
148			for _, e := range bucket {
149				if e.key != nil {
150					f(e.key, e.value)
151				}
152			}
153		}
154	}
155}
156
157// Keys returns a new slice containing the set of map keys.
158// The order is unspecified.
159func (m *Map) Keys() []types.Type {
160	keys := make([]types.Type, 0, m.Len())
161	m.Iterate(func(key types.Type, _ any) {
162		keys = append(keys, key)
163	})
164	return keys
165}
166
167func (m *Map) toString(values bool) string {
168	if m == nil {
169		return "{}"
170	}
171	var buf bytes.Buffer
172	fmt.Fprint(&buf, "{")
173	sep := ""
174	m.Iterate(func(key types.Type, value any) {
175		fmt.Fprint(&buf, sep)
176		sep = ", "
177		fmt.Fprint(&buf, key)
178		if values {
179			fmt.Fprintf(&buf, ": %q", value)
180		}
181	})
182	fmt.Fprint(&buf, "}")
183	return buf.String()
184}
185
186// String returns a string representation of the map's entries.
187// Values are printed using fmt.Sprintf("%v", v).
188// Order is unspecified.
189func (m *Map) String() string {
190	return m.toString(true)
191}
192
193// KeysString returns a string representation of the map's key set.
194// Order is unspecified.
195func (m *Map) KeysString() string {
196	return m.toString(false)
197}
198
199////////////////////////////////////////////////////////////////////////
200// Hasher
201
202// A Hasher maps each type to its hash value.
203// For efficiency, a hasher uses memoization; thus its memory
204// footprint grows monotonically over time.
205// Hashers are not thread-safe.
206// Hashers have reference semantics.
207// Call MakeHasher to create a Hasher.
208type Hasher struct {
209	memo map[types.Type]uint32
210
211	// ptrMap records pointer identity.
212	ptrMap map[any]uint32
213
214	// sigTParams holds type parameters from the signature being hashed.
215	// Signatures are considered identical modulo renaming of type parameters, so
216	// within the scope of a signature type the identity of the signature's type
217	// parameters is just their index.
218	//
219	// Since the language does not currently support referring to uninstantiated
220	// generic types or functions, and instantiated signatures do not have type
221	// parameter lists, we should never encounter a second non-empty type
222	// parameter list when hashing a generic signature.
223	sigTParams *types.TypeParamList
224}
225
226// MakeHasher returns a new Hasher instance.
227func MakeHasher() Hasher {
228	return Hasher{
229		memo:       make(map[types.Type]uint32),
230		ptrMap:     make(map[any]uint32),
231		sigTParams: nil,
232	}
233}
234
235// Hash computes a hash value for the given type t such that
236// Identical(t, t') => Hash(t) == Hash(t').
237func (h Hasher) Hash(t types.Type) uint32 {
238	hash, ok := h.memo[t]
239	if !ok {
240		hash = h.hashFor(t)
241		h.memo[t] = hash
242	}
243	return hash
244}
245
246// hashString computes the Fowler–Noll–Vo hash of s.
247func hashString(s string) uint32 {
248	var h uint32
249	for i := 0; i < len(s); i++ {
250		h ^= uint32(s[i])
251		h *= 16777619
252	}
253	return h
254}
255
256// hashFor computes the hash of t.
257func (h Hasher) hashFor(t types.Type) uint32 {
258	// See Identical for rationale.
259	switch t := t.(type) {
260	case *types.Basic:
261		return uint32(t.Kind())
262
263	case *aliases.Alias:
264		return h.Hash(aliases.Unalias(t))
265
266	case *types.Array:
267		return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())
268
269	case *types.Slice:
270		return 9049 + 2*h.Hash(t.Elem())
271
272	case *types.Struct:
273		var hash uint32 = 9059
274		for i, n := 0, t.NumFields(); i < n; i++ {
275			f := t.Field(i)
276			if f.Anonymous() {
277				hash += 8861
278			}
279			hash += hashString(t.Tag(i))
280			hash += hashString(f.Name()) // (ignore f.Pkg)
281			hash += h.Hash(f.Type())
282		}
283		return hash
284
285	case *types.Pointer:
286		return 9067 + 2*h.Hash(t.Elem())
287
288	case *types.Signature:
289		var hash uint32 = 9091
290		if t.Variadic() {
291			hash *= 8863
292		}
293
294		// Use a separate hasher for types inside of the signature, where type
295		// parameter identity is modified to be (index, constraint). We must use a
296		// new memo for this hasher as type identity may be affected by this
297		// masking. For example, in func[T any](*T), the identity of *T depends on
298		// whether we are mapping the argument in isolation, or recursively as part
299		// of hashing the signature.
300		//
301		// We should never encounter a generic signature while hashing another
302		// generic signature, but defensively set sigTParams only if h.mask is
303		// unset.
304		tparams := t.TypeParams()
305		if h.sigTParams == nil && tparams.Len() != 0 {
306			h = Hasher{
307				// There may be something more efficient than discarding the existing
308				// memo, but it would require detecting whether types are 'tainted' by
309				// references to type parameters.
310				memo: make(map[types.Type]uint32),
311				// Re-using ptrMap ensures that pointer identity is preserved in this
312				// hasher.
313				ptrMap:     h.ptrMap,
314				sigTParams: tparams,
315			}
316		}
317
318		for i := 0; i < tparams.Len(); i++ {
319			tparam := tparams.At(i)
320			hash += 7 * h.Hash(tparam.Constraint())
321		}
322
323		return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())
324
325	case *types.Union:
326		return h.hashUnion(t)
327
328	case *types.Interface:
329		// Interfaces are identical if they have the same set of methods, with
330		// identical names and types, and they have the same set of type
331		// restrictions. See go/types.identical for more details.
332		var hash uint32 = 9103
333
334		// Hash methods.
335		for i, n := 0, t.NumMethods(); i < n; i++ {
336			// Method order is not significant.
337			// Ignore m.Pkg().
338			m := t.Method(i)
339			// Use shallow hash on method signature to
340			// avoid anonymous interface cycles.
341			hash += 3*hashString(m.Name()) + 5*h.shallowHash(m.Type())
342		}
343
344		// Hash type restrictions.
345		terms, err := typeparams.InterfaceTermSet(t)
346		// if err != nil t has invalid type restrictions.
347		if err == nil {
348			hash += h.hashTermSet(terms)
349		}
350
351		return hash
352
353	case *types.Map:
354		return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem())
355
356	case *types.Chan:
357		return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem())
358
359	case *types.Named:
360		hash := h.hashPtr(t.Obj())
361		targs := t.TypeArgs()
362		for i := 0; i < targs.Len(); i++ {
363			targ := targs.At(i)
364			hash += 2 * h.Hash(targ)
365		}
366		return hash
367
368	case *types.TypeParam:
369		return h.hashTypeParam(t)
370
371	case *types.Tuple:
372		return h.hashTuple(t)
373	}
374
375	panic(fmt.Sprintf("%T: %v", t, t))
376}
377
378func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
379	// See go/types.identicalTypes for rationale.
380	n := tuple.Len()
381	hash := 9137 + 2*uint32(n)
382	for i := 0; i < n; i++ {
383		hash += 3 * h.Hash(tuple.At(i).Type())
384	}
385	return hash
386}
387
388func (h Hasher) hashUnion(t *types.Union) uint32 {
389	// Hash type restrictions.
390	terms, err := typeparams.UnionTermSet(t)
391	// if err != nil t has invalid type restrictions. Fall back on a non-zero
392	// hash.
393	if err != nil {
394		return 9151
395	}
396	return h.hashTermSet(terms)
397}
398
399func (h Hasher) hashTermSet(terms []*types.Term) uint32 {
400	hash := 9157 + 2*uint32(len(terms))
401	for _, term := range terms {
402		// term order is not significant.
403		termHash := h.Hash(term.Type())
404		if term.Tilde() {
405			termHash *= 9161
406		}
407		hash += 3 * termHash
408	}
409	return hash
410}
411
412// hashTypeParam returns a hash of the type parameter t, with a hash value
413// depending on whether t is contained in h.sigTParams.
414//
415// If h.sigTParams is set and contains t, then we are in the process of hashing
416// a signature, and the hash value of t must depend only on t's index and
417// constraint: signatures are considered identical modulo type parameter
418// renaming. To avoid infinite recursion, we only hash the type parameter
419// index, and rely on types.Identical to handle signatures where constraints
420// are not identical.
421//
422// Otherwise the hash of t depends only on t's pointer identity.
423func (h Hasher) hashTypeParam(t *types.TypeParam) uint32 {
424	if h.sigTParams != nil {
425		i := t.Index()
426		if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) {
427			return 9173 + 3*uint32(i)
428		}
429	}
430	return h.hashPtr(t.Obj())
431}
432
433// hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that
434// pointers values are not dependent on the GC.
435func (h Hasher) hashPtr(ptr any) uint32 {
436	if hash, ok := h.ptrMap[ptr]; ok {
437		return hash
438	}
439	hash := uint32(reflect.ValueOf(ptr).Pointer())
440	h.ptrMap[ptr] = hash
441	return hash
442}
443
444// shallowHash computes a hash of t without looking at any of its
445// element Types, to avoid potential anonymous cycles in the types of
446// interface methods.
447//
448// When an unnamed non-empty interface type appears anywhere among the
449// arguments or results of an interface method, there is a potential
450// for endless recursion. Consider:
451//
452//	type X interface { m() []*interface { X } }
453//
454// The problem is that the Methods of the interface in m's result type
455// include m itself; there is no mention of the named type X that
456// might help us break the cycle.
457// (See comment in go/types.identical, case *Interface, for more.)
458func (h Hasher) shallowHash(t types.Type) uint32 {
459	// t is the type of an interface method (Signature),
460	// its params or results (Tuples), or their immediate
461	// elements (mostly Slice, Pointer, Basic, Named),
462	// so there's no need to optimize anything else.
463	switch t := t.(type) {
464	case *aliases.Alias:
465		return h.shallowHash(aliases.Unalias(t))
466
467	case *types.Signature:
468		var hash uint32 = 604171
469		if t.Variadic() {
470			hash *= 971767
471		}
472		// The Signature/Tuple recursion is always finite
473		// and invariably shallow.
474		return hash + 1062599*h.shallowHash(t.Params()) + 1282529*h.shallowHash(t.Results())
475
476	case *types.Tuple:
477		n := t.Len()
478		hash := 9137 + 2*uint32(n)
479		for i := 0; i < n; i++ {
480			hash += 53471161 * h.shallowHash(t.At(i).Type())
481		}
482		return hash
483
484	case *types.Basic:
485		return 45212177 * uint32(t.Kind())
486
487	case *types.Array:
488		return 1524181 + 2*uint32(t.Len())
489
490	case *types.Slice:
491		return 2690201
492
493	case *types.Struct:
494		return 3326489
495
496	case *types.Pointer:
497		return 4393139
498
499	case *types.Union:
500		return 562448657
501
502	case *types.Interface:
503		return 2124679 // no recursion here
504
505	case *types.Map:
506		return 9109
507
508	case *types.Chan:
509		return 9127
510
511	case *types.Named:
512		return h.hashPtr(t.Obj())
513
514	case *types.TypeParam:
515		return h.hashPtr(t.Obj())
516	}
517	panic(fmt.Sprintf("shallowHash: %T: %v", t, t))
518}
519