1
2
3
4
5 package ssa
6
7
8
9 import (
10 "fmt"
11 "go/ast"
12 "go/token"
13 "go/types"
14 "io"
15 "os"
16 "sync"
17
18 "golang.org/x/tools/go/ast/astutil"
19 "golang.org/x/tools/go/types/typeutil"
20 "golang.org/x/tools/internal/typeparams"
21 )
22
23
24
25
26
27 func assert(p bool, msg string) {
28 if !p {
29 panic(msg)
30 }
31 }
32
33
34
35 func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }
36
37
38
39 func isBlankIdent(e ast.Expr) bool {
40 id, ok := e.(*ast.Ident)
41 return ok && id.Name == "_"
42 }
43
44
45
46
47 func isPointer(typ types.Type) bool {
48 _, ok := typ.Underlying().(*types.Pointer)
49 return ok
50 }
51
52
53 func isNonTypeParamInterface(t types.Type) bool {
54 return !typeparams.IsTypeParam(t) && types.IsInterface(t)
55 }
56
57
58 func isBasic(t types.Type) bool {
59 _, ok := t.(*types.Basic)
60 return ok
61 }
62
63
64 func isString(t types.Type) bool {
65 return isBasic(t) && t.(*types.Basic).Info()&types.IsString != 0
66 }
67
68
69 func isByteSlice(t types.Type) bool {
70 if b, ok := t.(*types.Slice); ok {
71 e, _ := b.Elem().(*types.Basic)
72 return e != nil && e.Kind() == types.Byte
73 }
74 return false
75 }
76
77
78 func isRuneSlice(t types.Type) bool {
79 if b, ok := t.(*types.Slice); ok {
80 e, _ := b.Elem().(*types.Basic)
81 return e != nil && e.Kind() == types.Rune
82 }
83 return false
84 }
85
86
87
88
89
90
91 func isBasicConvTypes(tset termList) bool {
92 basics := 0
93 all := underIs(tset, func(t types.Type) bool {
94 if isBasic(t) {
95 basics++
96 return true
97 }
98 return isByteSlice(t) || isRuneSlice(t)
99 })
100 return all && basics >= 1 && tset.Len()-basics <= 1
101 }
102
103
104 func deref(typ types.Type) types.Type {
105 if p, ok := typ.Underlying().(*types.Pointer); ok {
106 return p.Elem()
107 }
108 return typ
109 }
110
111
112 func recvType(obj *types.Func) types.Type {
113 return obj.Type().(*types.Signature).Recv().Type()
114 }
115
116
117 func isUntyped(typ types.Type) bool {
118 b, ok := typ.(*types.Basic)
119 return ok && b.Info()&types.IsUntyped != 0
120 }
121
122
123
124
125
126 func logStack(format string, args ...interface{}) func() {
127 msg := fmt.Sprintf(format, args...)
128 io.WriteString(os.Stderr, msg)
129 io.WriteString(os.Stderr, "\n")
130 return func() {
131 io.WriteString(os.Stderr, msg)
132 io.WriteString(os.Stderr, " end\n")
133 }
134 }
135
136
137 func newVar(name string, typ types.Type) *types.Var {
138 return types.NewParam(token.NoPos, nil, name, typ)
139 }
140
141
142 func anonVar(typ types.Type) *types.Var {
143 return newVar("", typ)
144 }
145
146 var lenResults = types.NewTuple(anonVar(tInt))
147
148
149 func makeLen(T types.Type) *Builtin {
150 lenParams := types.NewTuple(anonVar(T))
151 return &Builtin{
152 name: "len",
153 sig: types.NewSignature(nil, lenParams, lenResults, false),
154 }
155 }
156
157
158 func nonbasicTypes(ts []types.Type) []types.Type {
159 if len(ts) == 0 {
160 return nil
161 }
162 added := make(map[types.Type]bool)
163 var filtered []types.Type
164 for _, T := range ts {
165 if !isBasic(T) {
166 if !added[T] {
167 added[T] = true
168 filtered = append(filtered, T)
169 }
170 }
171 }
172 return filtered
173 }
174
175
176
177 func receiverTypeArgs(obj *types.Func) []types.Type {
178 rtype := recvType(obj)
179 if rtype == nil {
180 return nil
181 }
182 if isPointer(rtype) {
183 rtype = rtype.(*types.Pointer).Elem()
184 }
185 named, ok := rtype.(*types.Named)
186 if !ok {
187 return nil
188 }
189 ts := typeparams.NamedTypeArgs(named)
190 if ts.Len() == 0 {
191 return nil
192 }
193 targs := make([]types.Type, ts.Len())
194 for i := 0; i < ts.Len(); i++ {
195 targs[i] = ts.At(i)
196 }
197 return targs
198 }
199
200
201
202 func recvAsFirstArg(sig *types.Signature) *types.Signature {
203 params := make([]*types.Var, 0, 1+sig.Params().Len())
204 params = append(params, sig.Recv())
205 for i := 0; i < sig.Params().Len(); i++ {
206 params = append(params, sig.Params().At(i))
207 }
208 return typeparams.NewSignatureType(nil, nil, nil, types.NewTuple(params...), sig.Results(), sig.Variadic())
209 }
210
211
212
213 func instance(info *types.Info, expr ast.Expr) bool {
214
215
216 var id *ast.Ident
217 switch x := expr.(type) {
218 case *ast.Ident:
219 id = x
220 case *ast.SelectorExpr:
221 id = x.Sel
222 default:
223 return false
224 }
225 _, ok := typeparams.GetInstances(info)[id]
226 return ok
227 }
228
229
230 func instanceArgs(info *types.Info, id *ast.Ident) []types.Type {
231 targList := typeparams.GetInstances(info)[id].TypeArgs
232 if targList == nil {
233 return nil
234 }
235
236 targs := make([]types.Type, targList.Len())
237 for i, n := 0, targList.Len(); i < n; i++ {
238 targs[i] = targList.At(i)
239 }
240 return targs
241 }
242
243
244
245 type canonizer struct {
246 mu sync.Mutex
247 types typeutil.Map
248 lists typeListMap
249 }
250
251 func newCanonizer() *canonizer {
252 c := &canonizer{}
253 h := typeutil.MakeHasher()
254 c.types.SetHasher(h)
255 c.lists.hasher = h
256 return c
257 }
258
259
260
261 func (c *canonizer) List(ts []types.Type) *typeList {
262 if len(ts) == 0 {
263 return nil
264 }
265
266 c.mu.Lock()
267 defer c.mu.Unlock()
268 return c.lists.rep(ts)
269 }
270
271
272 func (c *canonizer) Type(T types.Type) types.Type {
273 c.mu.Lock()
274 defer c.mu.Unlock()
275
276 if r := c.types.At(T); r != nil {
277 return r.(types.Type)
278 }
279 c.types.Set(T, T)
280 return T
281 }
282
283
284 type typeList []types.Type
285
286 func (l *typeList) identical(ts []types.Type) bool {
287 if l == nil {
288 return len(ts) == 0
289 }
290 n := len(*l)
291 if len(ts) != n {
292 return false
293 }
294 for i, left := range *l {
295 right := ts[i]
296 if !types.Identical(left, right) {
297 return false
298 }
299 }
300 return true
301 }
302
303 type typeListMap struct {
304 hasher typeutil.Hasher
305 buckets map[uint32][]*typeList
306 }
307
308
309 func (m *typeListMap) rep(ts []types.Type) *typeList {
310 if m == nil || len(ts) == 0 {
311 return nil
312 }
313
314 if m.buckets == nil {
315 m.buckets = make(map[uint32][]*typeList)
316 }
317
318 h := m.hash(ts)
319 bucket := m.buckets[h]
320 for _, l := range bucket {
321 if l.identical(ts) {
322 return l
323 }
324 }
325
326
327 cp := make(typeList, len(ts))
328 copy(cp, ts)
329 rep := &cp
330
331 m.buckets[h] = append(bucket, rep)
332 return rep
333 }
334
335 func (m *typeListMap) hash(ts []types.Type) uint32 {
336 if m == nil {
337 return 0
338 }
339
340 n := len(ts)
341 h := uint32(13619) + 2*uint32(n)
342 for i := 0; i < n; i++ {
343 h += 3 * m.hasher.Hash(ts[i])
344 }
345 return h
346 }
347
348
349 func (canon *canonizer) instantiateMethod(m *types.Func, targs []types.Type, ctxt *typeparams.Context) *types.Func {
350 recv := recvType(m)
351 if p, ok := recv.(*types.Pointer); ok {
352 recv = p.Elem()
353 }
354 named := recv.(*types.Named)
355 inst, err := typeparams.Instantiate(ctxt, typeparams.NamedTypeOrigin(named), targs, false)
356 if err != nil {
357 panic(err)
358 }
359 rep := canon.Type(inst)
360 obj, _, _ := types.LookupFieldOrMethod(rep, true, m.Pkg(), m.Name())
361 return obj.(*types.Func)
362 }
363
View as plain text