Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / types / typeutil / methodsetcache.go
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 // This file implements a cache of method sets.
6
7 package typeutil
8
9 import (
10         "go/types"
11         "sync"
12 )
13
14 // A MethodSetCache records the method set of each type T for which
15 // MethodSet(T) is called so that repeat queries are fast.
16 // The zero value is a ready-to-use cache instance.
17 type MethodSetCache struct {
18         mu     sync.Mutex
19         named  map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N
20         others map[types.Type]*types.MethodSet                            // all other types
21 }
22
23 // MethodSet returns the method set of type T.  It is thread-safe.
24 //
25 // If cache is nil, this function is equivalent to types.NewMethodSet(T).
26 // Utility functions can thus expose an optional *MethodSetCache
27 // parameter to clients that care about performance.
28 //
29 func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
30         if cache == nil {
31                 return types.NewMethodSet(T)
32         }
33         cache.mu.Lock()
34         defer cache.mu.Unlock()
35
36         switch T := T.(type) {
37         case *types.Named:
38                 return cache.lookupNamed(T).value
39
40         case *types.Pointer:
41                 if N, ok := T.Elem().(*types.Named); ok {
42                         return cache.lookupNamed(N).pointer
43                 }
44         }
45
46         // all other types
47         // (The map uses pointer equivalence, not type identity.)
48         mset := cache.others[T]
49         if mset == nil {
50                 mset = types.NewMethodSet(T)
51                 if cache.others == nil {
52                         cache.others = make(map[types.Type]*types.MethodSet)
53                 }
54                 cache.others[T] = mset
55         }
56         return mset
57 }
58
59 func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {
60         if cache.named == nil {
61                 cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })
62         }
63         // Avoid recomputing mset(*T) for each distinct Pointer
64         // instance whose underlying type is a named type.
65         msets, ok := cache.named[named]
66         if !ok {
67                 msets.value = types.NewMethodSet(named)
68                 msets.pointer = types.NewMethodSet(types.NewPointer(named))
69                 cache.named[named] = msets
70         }
71         return msets
72 }