github.com/goplus/llgo@v0.8.3/internal/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 8 9 import ( 10 "bytes" 11 "fmt" 12 "go/types" 13 "reflect" 14 15 "github.com/goplus/llgo/internal/aliases" 16 "github.com/goplus/llgo/internal/typeparams" 17 ) 18 19 // Map is a hash-table-based mapping from types (types.Type) to 20 // arbitrary interface{} 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. 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 func (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. 66 func (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. 85 func (m *Map) At(key types.Type) interface{} { 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. 98 func (m *Map) Set(key types.Type, value interface{}) (prev interface{}) { 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. 131 func (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. 145 func (m *Map) Iterate(f func(key types.Type, value interface{})) { 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. 159 func (m *Map) Keys() []types.Type { 160 keys := make([]types.Type, 0, m.Len()) 161 m.Iterate(func(key types.Type, _ interface{}) { 162 keys = append(keys, key) 163 }) 164 return keys 165 } 166 167 func (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 interface{}) { 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. 189 func (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. 195 func (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. 208 type Hasher struct { 209 memo map[types.Type]uint32 210 211 // ptrMap records pointer identity. 212 ptrMap map[interface{}]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. 227 func MakeHasher() Hasher { 228 return Hasher{ 229 memo: make(map[types.Type]uint32), 230 ptrMap: make(map[interface{}]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'). 237 func (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. 247 func 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 func HashSig(h Hasher, t *types.Signature) uint32 { 257 var hash uint32 = 9091 258 if t.Variadic() { 259 hash *= 8863 260 } 261 262 // Use a separate hasher for types inside of the signature, where type 263 // parameter identity is modified to be (index, constraint). We must use a 264 // new memo for this hasher as type identity may be affected by this 265 // masking. For example, in func[T any](*T), the identity of *T depends on 266 // whether we are mapping the argument in isolation, or recursively as part 267 // of hashing the signature. 268 // 269 // We should never encounter a generic signature while hashing another 270 // generic signature, but defensively set sigTParams only if h.mask is 271 // unset. 272 tparams := t.TypeParams() 273 if h.sigTParams == nil && tparams.Len() != 0 { 274 h = Hasher{ 275 // There may be something more efficient than discarding the existing 276 // memo, but it would require detecting whether types are 'tainted' by 277 // references to type parameters. 278 memo: make(map[types.Type]uint32), 279 // Re-using ptrMap ensures that pointer identity is preserved in this 280 // hasher. 281 ptrMap: h.ptrMap, 282 sigTParams: tparams, 283 } 284 } 285 286 for i := 0; i < tparams.Len(); i++ { 287 tparam := tparams.At(i) 288 hash += 7 * h.Hash(tparam.Constraint()) 289 } 290 291 return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results()) 292 } 293 294 // hashFor computes the hash of t. 295 func (h Hasher) hashFor(t types.Type) uint32 { 296 // See Identical for rationale. 297 switch t := t.(type) { 298 case *types.Basic: 299 return uint32(t.Kind()) 300 301 case *aliases.Alias: 302 return h.Hash(t.Underlying()) 303 304 case *types.Array: 305 return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem()) 306 307 case *types.Slice: 308 return 9049 + 2*h.Hash(t.Elem()) 309 310 case *types.Struct: 311 var hash uint32 = 9059 312 for i, n := 0, t.NumFields(); i < n; i++ { 313 f := t.Field(i) 314 if f.Anonymous() { 315 hash += 8861 316 } 317 hash += hashString(t.Tag(i)) 318 hash += hashString(f.Name()) // (ignore f.Pkg) 319 hash += h.Hash(f.Type()) 320 } 321 return hash 322 323 case *types.Pointer: 324 return 9067 + 2*h.Hash(t.Elem()) 325 326 case *types.Signature: 327 return HashSig(h, t) 328 329 case *types.Union: 330 return h.hashUnion(t) 331 332 case *types.Interface: 333 // Interfaces are identical if they have the same set of methods, with 334 // identical names and types, and they have the same set of type 335 // restrictions. See go/types.identical for more details. 336 var hash uint32 = 9103 337 338 // Hash methods. 339 for i, n := 0, t.NumMethods(); i < n; i++ { 340 // Method order is not significant. 341 // Ignore m.Pkg(). 342 m := t.Method(i) 343 // Use shallow hash on method signature to 344 // avoid anonymous interface cycles. 345 hash += 3*hashString(m.Name()) + 5*h.shallowHash(m.Type()) 346 } 347 348 // Hash type restrictions. 349 terms, err := typeparams.InterfaceTermSet(t) 350 // if err != nil t has invalid type restrictions. 351 if err == nil { 352 hash += h.hashTermSet(terms) 353 } 354 355 return hash 356 357 case *types.Map: 358 return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem()) 359 360 case *types.Chan: 361 return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem()) 362 363 case *types.Named: 364 hash := h.hashPtr(t.Obj()) 365 targs := t.TypeArgs() 366 for i := 0; i < targs.Len(); i++ { 367 targ := targs.At(i) 368 hash += 2 * h.Hash(targ) 369 } 370 return hash 371 372 case *types.TypeParam: 373 return h.hashTypeParam(t) 374 375 case *types.Tuple: 376 return h.hashTuple(t) 377 378 case interface{ Hash(h Hasher) uint32 }: 379 return t.Hash(h) 380 } 381 382 panic(fmt.Sprintf("%T: %v", t, t)) 383 } 384 385 func (h Hasher) hashTuple(tuple *types.Tuple) uint32 { 386 // See go/types.identicalTypes for rationale. 387 n := tuple.Len() 388 hash := 9137 + 2*uint32(n) 389 for i := 0; i < n; i++ { 390 hash += 3 * h.Hash(tuple.At(i).Type()) 391 } 392 return hash 393 } 394 395 func (h Hasher) hashUnion(t *types.Union) uint32 { 396 // Hash type restrictions. 397 terms, err := typeparams.UnionTermSet(t) 398 // if err != nil t has invalid type restrictions. Fall back on a non-zero 399 // hash. 400 if err != nil { 401 return 9151 402 } 403 return h.hashTermSet(terms) 404 } 405 406 func (h Hasher) hashTermSet(terms []*types.Term) uint32 { 407 hash := 9157 + 2*uint32(len(terms)) 408 for _, term := range terms { 409 // term order is not significant. 410 termHash := h.Hash(term.Type()) 411 if term.Tilde() { 412 termHash *= 9161 413 } 414 hash += 3 * termHash 415 } 416 return hash 417 } 418 419 // hashTypeParam returns a hash of the type parameter t, with a hash value 420 // depending on whether t is contained in h.sigTParams. 421 // 422 // If h.sigTParams is set and contains t, then we are in the process of hashing 423 // a signature, and the hash value of t must depend only on t's index and 424 // constraint: signatures are considered identical modulo type parameter 425 // renaming. To avoid infinite recursion, we only hash the type parameter 426 // index, and rely on types.Identical to handle signatures where constraints 427 // are not identical. 428 // 429 // Otherwise the hash of t depends only on t's pointer identity. 430 func (h Hasher) hashTypeParam(t *types.TypeParam) uint32 { 431 if h.sigTParams != nil { 432 i := t.Index() 433 if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) { 434 return 9173 + 3*uint32(i) 435 } 436 } 437 return h.hashPtr(t.Obj()) 438 } 439 440 // hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that 441 // pointers values are not dependent on the GC. 442 func (h Hasher) hashPtr(ptr interface{}) uint32 { 443 if hash, ok := h.ptrMap[ptr]; ok { 444 return hash 445 } 446 hash := uint32(reflect.ValueOf(ptr).Pointer()) 447 h.ptrMap[ptr] = hash 448 return hash 449 } 450 451 // shallowHash computes a hash of t without looking at any of its 452 // element Types, to avoid potential anonymous cycles in the types of 453 // interface methods. 454 // 455 // When an unnamed non-empty interface type appears anywhere among the 456 // arguments or results of an interface method, there is a potential 457 // for endless recursion. Consider: 458 // 459 // type X interface { m() []*interface { X } } 460 // 461 // The problem is that the Methods of the interface in m's result type 462 // include m itself; there is no mention of the named type X that 463 // might help us break the cycle. 464 // (See comment in go/types.identical, case *Interface, for more.) 465 func (h Hasher) shallowHash(t types.Type) uint32 { 466 // t is the type of an interface method (Signature), 467 // its params or results (Tuples), or their immediate 468 // elements (mostly Slice, Pointer, Basic, Named), 469 // so there's no need to optimize anything else. 470 switch t := t.(type) { 471 case *aliases.Alias: 472 return h.shallowHash(t.Underlying()) 473 474 case *types.Signature: 475 var hash uint32 = 604171 476 if t.Variadic() { 477 hash *= 971767 478 } 479 // The Signature/Tuple recursion is always finite 480 // and invariably shallow. 481 return hash + 1062599*h.shallowHash(t.Params()) + 1282529*h.shallowHash(t.Results()) 482 483 case *types.Tuple: 484 n := t.Len() 485 hash := 9137 + 2*uint32(n) 486 for i := 0; i < n; i++ { 487 hash += 53471161 * h.shallowHash(t.At(i).Type()) 488 } 489 return hash 490 491 case *types.Basic: 492 return 45212177 * uint32(t.Kind()) 493 494 case *types.Array: 495 return 1524181 + 2*uint32(t.Len()) 496 497 case *types.Slice: 498 return 2690201 499 500 case *types.Struct: 501 return 3326489 502 503 case *types.Pointer: 504 return 4393139 505 506 case *types.Union: 507 return 562448657 508 509 case *types.Interface: 510 return 2124679 // no recursion here 511 512 case *types.Map: 513 return 9109 514 515 case *types.Chan: 516 return 9127 517 518 case *types.Named: 519 return h.hashPtr(t.Obj()) 520 521 case *types.TypeParam: 522 return h.hashPtr(t.Obj()) 523 } 524 panic(fmt.Sprintf("shallowHash: %T: %v", t, t)) 525 }