github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/types/typeutil/map.go (about)

     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 interface{} values.
     7  package typeutil // import "github.com/powerman/golang-tools/go/types/typeutil"
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"go/types"
    13  	"reflect"
    14  
    15  	"github.com/powerman/golang-tools/internal/typeparams"
    16  )
    17  
    18  // Map is a hash-table-based mapping from types (types.Type) to
    19  // arbitrary interface{} values.  The concrete types that implement
    20  // the Type interface are pointers.  Since they are not canonicalized,
    21  // == cannot be used to check for equivalence, and thus we cannot
    22  // simply use a Go map.
    23  //
    24  // Just as with map[K]V, a nil *Map is a valid empty map.
    25  //
    26  // Not thread-safe.
    27  //
    28  type 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.
    35  type entry struct {
    36  	key   types.Type
    37  	value interface{}
    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.
    60  //
    61  func (m *Map) SetHasher(hasher Hasher) {
    62  	m.hasher = hasher
    63  }
    64  
    65  // Delete removes the entry with the given key, if any.
    66  // It returns true if the entry was found.
    67  //
    68  func (m *Map) Delete(key types.Type) bool {
    69  	if m != nil && m.table != nil {
    70  		hash := m.hasher.Hash(key)
    71  		bucket := m.table[hash]
    72  		for i, e := range bucket {
    73  			if e.key != nil && types.Identical(key, e.key) {
    74  				// We can't compact the bucket as it
    75  				// would disturb iterators.
    76  				bucket[i] = entry{}
    77  				m.length--
    78  				return true
    79  			}
    80  		}
    81  	}
    82  	return false
    83  }
    84  
    85  // At returns the map entry for the given key.
    86  // The result is nil if the entry is not present.
    87  //
    88  func (m *Map) At(key types.Type) interface{} {
    89  	if m != nil && m.table != nil {
    90  		for _, e := range m.table[m.hasher.Hash(key)] {
    91  			if e.key != nil && types.Identical(key, e.key) {
    92  				return e.value
    93  			}
    94  		}
    95  	}
    96  	return nil
    97  }
    98  
    99  // Set sets the map entry for key to val,
   100  // and returns the previous entry, if any.
   101  func (m *Map) Set(key types.Type, value interface{}) (prev interface{}) {
   102  	if m.table != nil {
   103  		hash := m.hasher.Hash(key)
   104  		bucket := m.table[hash]
   105  		var hole *entry
   106  		for i, e := range bucket {
   107  			if e.key == nil {
   108  				hole = &bucket[i]
   109  			} else if types.Identical(key, e.key) {
   110  				prev = e.value
   111  				bucket[i].value = value
   112  				return
   113  			}
   114  		}
   115  
   116  		if hole != nil {
   117  			*hole = entry{key, value} // overwrite deleted entry
   118  		} else {
   119  			m.table[hash] = append(bucket, entry{key, value})
   120  		}
   121  	} else {
   122  		if m.hasher.memo == nil {
   123  			m.hasher = MakeHasher()
   124  		}
   125  		hash := m.hasher.Hash(key)
   126  		m.table = map[uint32][]entry{hash: {entry{key, value}}}
   127  	}
   128  
   129  	m.length++
   130  	return
   131  }
   132  
   133  // Len returns the number of map entries.
   134  func (m *Map) Len() int {
   135  	if m != nil {
   136  		return m.length
   137  	}
   138  	return 0
   139  }
   140  
   141  // Iterate calls function f on each entry in the map in unspecified order.
   142  //
   143  // If f should mutate the map, Iterate provides the same guarantees as
   144  // Go maps: if f deletes a map entry that Iterate has not yet reached,
   145  // f will not be invoked for it, but if f inserts a map entry that
   146  // Iterate has not yet reached, whether or not f will be invoked for
   147  // it is unspecified.
   148  //
   149  func (m *Map) Iterate(f func(key types.Type, value interface{})) {
   150  	if m != nil {
   151  		for _, bucket := range m.table {
   152  			for _, e := range bucket {
   153  				if e.key != nil {
   154  					f(e.key, e.value)
   155  				}
   156  			}
   157  		}
   158  	}
   159  }
   160  
   161  // Keys returns a new slice containing the set of map keys.
   162  // The order is unspecified.
   163  func (m *Map) Keys() []types.Type {
   164  	keys := make([]types.Type, 0, m.Len())
   165  	m.Iterate(func(key types.Type, _ interface{}) {
   166  		keys = append(keys, key)
   167  	})
   168  	return keys
   169  }
   170  
   171  func (m *Map) toString(values bool) string {
   172  	if m == nil {
   173  		return "{}"
   174  	}
   175  	var buf bytes.Buffer
   176  	fmt.Fprint(&buf, "{")
   177  	sep := ""
   178  	m.Iterate(func(key types.Type, value interface{}) {
   179  		fmt.Fprint(&buf, sep)
   180  		sep = ", "
   181  		fmt.Fprint(&buf, key)
   182  		if values {
   183  			fmt.Fprintf(&buf, ": %q", value)
   184  		}
   185  	})
   186  	fmt.Fprint(&buf, "}")
   187  	return buf.String()
   188  }
   189  
   190  // String returns a string representation of the map's entries.
   191  // Values are printed using fmt.Sprintf("%v", v).
   192  // Order is unspecified.
   193  //
   194  func (m *Map) String() string {
   195  	return m.toString(true)
   196  }
   197  
   198  // KeysString returns a string representation of the map's key set.
   199  // Order is unspecified.
   200  //
   201  func (m *Map) KeysString() string {
   202  	return m.toString(false)
   203  }
   204  
   205  ////////////////////////////////////////////////////////////////////////
   206  // Hasher
   207  
   208  // A Hasher maps each type to its hash value.
   209  // For efficiency, a hasher uses memoization; thus its memory
   210  // footprint grows monotonically over time.
   211  // Hashers are not thread-safe.
   212  // Hashers have reference semantics.
   213  // Call MakeHasher to create a Hasher.
   214  type Hasher struct {
   215  	memo map[types.Type]uint32
   216  
   217  	// ptrMap records pointer identity.
   218  	ptrMap map[interface{}]uint32
   219  
   220  	// sigTParams holds type parameters from the signature being hashed.
   221  	// Signatures are considered identical modulo renaming of type parameters, so
   222  	// within the scope of a signature type the identity of the signature's type
   223  	// parameters is just their index.
   224  	//
   225  	// Since the language does not currently support referring to uninstantiated
   226  	// generic types or functions, and instantiated signatures do not have type
   227  	// parameter lists, we should never encounter a second non-empty type
   228  	// parameter list when hashing a generic signature.
   229  	sigTParams *typeparams.TypeParamList
   230  }
   231  
   232  // MakeHasher returns a new Hasher instance.
   233  func MakeHasher() Hasher {
   234  	return Hasher{
   235  		memo:       make(map[types.Type]uint32),
   236  		ptrMap:     make(map[interface{}]uint32),
   237  		sigTParams: nil,
   238  	}
   239  }
   240  
   241  // Hash computes a hash value for the given type t such that
   242  // Identical(t, t') => Hash(t) == Hash(t').
   243  func (h Hasher) Hash(t types.Type) uint32 {
   244  	hash, ok := h.memo[t]
   245  	if !ok {
   246  		hash = h.hashFor(t)
   247  		h.memo[t] = hash
   248  	}
   249  	return hash
   250  }
   251  
   252  // hashString computes the Fowler–Noll–Vo hash of s.
   253  func hashString(s string) uint32 {
   254  	var h uint32
   255  	for i := 0; i < len(s); i++ {
   256  		h ^= uint32(s[i])
   257  		h *= 16777619
   258  	}
   259  	return h
   260  }
   261  
   262  // hashFor computes the hash of t.
   263  func (h Hasher) hashFor(t types.Type) uint32 {
   264  	// See Identical for rationale.
   265  	switch t := t.(type) {
   266  	case *types.Basic:
   267  		return uint32(t.Kind())
   268  
   269  	case *types.Array:
   270  		return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())
   271  
   272  	case *types.Slice:
   273  		return 9049 + 2*h.Hash(t.Elem())
   274  
   275  	case *types.Struct:
   276  		var hash uint32 = 9059
   277  		for i, n := 0, t.NumFields(); i < n; i++ {
   278  			f := t.Field(i)
   279  			if f.Anonymous() {
   280  				hash += 8861
   281  			}
   282  			hash += hashString(t.Tag(i))
   283  			hash += hashString(f.Name()) // (ignore f.Pkg)
   284  			hash += h.Hash(f.Type())
   285  		}
   286  		return hash
   287  
   288  	case *types.Pointer:
   289  		return 9067 + 2*h.Hash(t.Elem())
   290  
   291  	case *types.Signature:
   292  		var hash uint32 = 9091
   293  		if t.Variadic() {
   294  			hash *= 8863
   295  		}
   296  
   297  		// Use a separate hasher for types inside of the signature, where type
   298  		// parameter identity is modified to be (index, constraint). We must use a
   299  		// new memo for this hasher as type identity may be affected by this
   300  		// masking. For example, in func[T any](*T), the identity of *T depends on
   301  		// whether we are mapping the argument in isolation, or recursively as part
   302  		// of hashing the signature.
   303  		//
   304  		// We should never encounter a generic signature while hashing another
   305  		// generic signature, but defensively set sigTParams only if h.mask is
   306  		// unset.
   307  		tparams := typeparams.ForSignature(t)
   308  		if h.sigTParams == nil && tparams.Len() != 0 {
   309  			h = Hasher{
   310  				// There may be something more efficient than discarding the existing
   311  				// memo, but it would require detecting whether types are 'tainted' by
   312  				// references to type parameters.
   313  				memo: make(map[types.Type]uint32),
   314  				// Re-using ptrMap ensures that pointer identity is preserved in this
   315  				// hasher.
   316  				ptrMap:     h.ptrMap,
   317  				sigTParams: tparams,
   318  			}
   319  		}
   320  
   321  		for i := 0; i < tparams.Len(); i++ {
   322  			tparam := tparams.At(i)
   323  			hash += 7 * h.Hash(tparam.Constraint())
   324  		}
   325  
   326  		return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())
   327  
   328  	case *typeparams.Union:
   329  		return h.hashUnion(t)
   330  
   331  	case *types.Interface:
   332  		// Interfaces are identical if they have the same set of methods, with
   333  		// identical names and types, and they have the same set of type
   334  		// restrictions. See go/types.identical for more details.
   335  		var hash uint32 = 9103
   336  
   337  		// Hash methods.
   338  		for i, n := 0, t.NumMethods(); i < n; i++ {
   339  			// Method order is not significant.
   340  			// Ignore m.Pkg().
   341  			m := t.Method(i)
   342  			hash += 3*hashString(m.Name()) + 5*h.Hash(m.Type())
   343  		}
   344  
   345  		// Hash type restrictions.
   346  		terms, err := typeparams.InterfaceTermSet(t)
   347  		// if err != nil t has invalid type restrictions.
   348  		if err == nil {
   349  			hash += h.hashTermSet(terms)
   350  		}
   351  
   352  		return hash
   353  
   354  	case *types.Map:
   355  		return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem())
   356  
   357  	case *types.Chan:
   358  		return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem())
   359  
   360  	case *types.Named:
   361  		hash := h.hashPtr(t.Obj())
   362  		targs := typeparams.NamedTypeArgs(t)
   363  		for i := 0; i < targs.Len(); i++ {
   364  			targ := targs.At(i)
   365  			hash += 2 * h.Hash(targ)
   366  		}
   367  		return hash
   368  
   369  	case *typeparams.TypeParam:
   370  		return h.hashTypeParam(t)
   371  
   372  	case *types.Tuple:
   373  		return h.hashTuple(t)
   374  	}
   375  
   376  	panic(fmt.Sprintf("%T: %v", t, t))
   377  }
   378  
   379  func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
   380  	// See go/types.identicalTypes for rationale.
   381  	n := tuple.Len()
   382  	hash := 9137 + 2*uint32(n)
   383  	for i := 0; i < n; i++ {
   384  		hash += 3 * h.Hash(tuple.At(i).Type())
   385  	}
   386  	return hash
   387  }
   388  
   389  func (h Hasher) hashUnion(t *typeparams.Union) uint32 {
   390  	// Hash type restrictions.
   391  	terms, err := typeparams.UnionTermSet(t)
   392  	// if err != nil t has invalid type restrictions. Fall back on a non-zero
   393  	// hash.
   394  	if err != nil {
   395  		return 9151
   396  	}
   397  	return h.hashTermSet(terms)
   398  }
   399  
   400  func (h Hasher) hashTermSet(terms []*typeparams.Term) uint32 {
   401  	hash := 9157 + 2*uint32(len(terms))
   402  	for _, term := range terms {
   403  		// term order is not significant.
   404  		termHash := h.Hash(term.Type())
   405  		if term.Tilde() {
   406  			termHash *= 9161
   407  		}
   408  		hash += 3 * termHash
   409  	}
   410  	return hash
   411  }
   412  
   413  // hashTypeParam returns a hash of the type parameter t, with a hash value
   414  // depending on whether t is contained in h.sigTParams.
   415  //
   416  // If h.sigTParams is set and contains t, then we are in the process of hashing
   417  // a signature, and the hash value of t must depend only on t's index and
   418  // constraint: signatures are considered identical modulo type parameter
   419  // renaming. To avoid infinite recursion, we only hash the type parameter
   420  // index, and rely on types.Identical to handle signatures where constraints
   421  // are not identical.
   422  //
   423  // Otherwise the hash of t depends only on t's pointer identity.
   424  func (h Hasher) hashTypeParam(t *typeparams.TypeParam) uint32 {
   425  	if h.sigTParams != nil {
   426  		i := t.Index()
   427  		if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) {
   428  			return 9173 + 3*uint32(i)
   429  		}
   430  	}
   431  	return h.hashPtr(t.Obj())
   432  }
   433  
   434  // hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that
   435  // pointers values are not dependent on the GC.
   436  func (h Hasher) hashPtr(ptr interface{}) uint32 {
   437  	if hash, ok := h.ptrMap[ptr]; ok {
   438  		return hash
   439  	}
   440  	hash := uint32(reflect.ValueOf(ptr).Pointer())
   441  	h.ptrMap[ptr] = hash
   442  	return hash
   443  }