1
2
3
4
5
6
7
8
9
10
11
12 package satisfy
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 import (
39 "fmt"
40 "go/ast"
41 "go/token"
42 "go/types"
43
44 "golang.org/x/tools/go/types/typeutil"
45 "golang.org/x/tools/internal/typeparams"
46 )
47
48
49
50
51
52
53
54 type Constraint struct {
55 LHS, RHS types.Type
56 }
57
58
59
60
61
62
63
64
65
66 type Finder struct {
67 Result map[Constraint]bool
68 msetcache typeutil.MethodSetCache
69
70
71 info *types.Info
72 sig *types.Signature
73 }
74
75
76
77
78
79
80
81
82
83
84 func (f *Finder) Find(info *types.Info, files []*ast.File) {
85 if info.Defs == nil || info.Uses == nil || info.Selections == nil || info.Types == nil {
86 panic("Finder.Find: one of info.{Defs,Uses,Selections.Types} is not populated")
87 }
88 if f.Result == nil {
89 f.Result = make(map[Constraint]bool)
90 }
91
92 f.info = info
93 for _, file := range files {
94 for _, d := range file.Decls {
95 switch d := d.(type) {
96 case *ast.GenDecl:
97 if d.Tok == token.VAR {
98 for _, spec := range d.Specs {
99 f.valueSpec(spec.(*ast.ValueSpec))
100 }
101 }
102
103 case *ast.FuncDecl:
104 if d.Body != nil {
105 f.sig = f.info.Defs[d.Name].Type().(*types.Signature)
106 f.stmt(d.Body)
107 f.sig = nil
108 }
109 }
110 }
111 }
112 f.info = nil
113 }
114
115 var (
116 tInvalid = types.Typ[types.Invalid]
117 tUntypedBool = types.Typ[types.UntypedBool]
118 tUntypedNil = types.Typ[types.UntypedNil]
119 )
120
121
122 func (f *Finder) exprN(e ast.Expr) types.Type {
123 typ := f.info.Types[e].Type.(*types.Tuple)
124 switch e := e.(type) {
125 case *ast.ParenExpr:
126 return f.exprN(e.X)
127
128 case *ast.CallExpr:
129
130 sig := typeparams.CoreType(f.expr(e.Fun)).(*types.Signature)
131 f.call(sig, e.Args)
132
133 case *ast.IndexExpr:
134
135 x := f.expr(e.X)
136 f.assign(f.expr(e.Index), typeparams.CoreType(x).(*types.Map).Key())
137
138 case *ast.TypeAssertExpr:
139
140 f.typeAssert(f.expr(e.X), typ.At(0).Type())
141
142 case *ast.UnaryExpr:
143
144 f.expr(e.X)
145
146 default:
147 panic(e)
148 }
149 return typ
150 }
151
152 func (f *Finder) call(sig *types.Signature, args []ast.Expr) {
153 if len(args) == 0 {
154 return
155 }
156
157
158 if _, ok := args[len(args)-1].(*ast.Ellipsis); ok {
159 for i, arg := range args {
160
161 f.assign(sig.Params().At(i).Type(), f.expr(arg))
162 }
163 return
164 }
165
166 var argtypes []types.Type
167
168
169 if tuple, ok := f.info.Types[args[0]].Type.(*types.Tuple); ok {
170
171 f.expr(args[0])
172
173 for v := range tuple.Variables() {
174 argtypes = append(argtypes, v.Type())
175 }
176 } else {
177 for _, arg := range args {
178 argtypes = append(argtypes, f.expr(arg))
179 }
180 }
181
182
183 if !sig.Variadic() {
184 for i, argtype := range argtypes {
185 f.assign(sig.Params().At(i).Type(), argtype)
186 }
187 } else {
188
189 nnormals := sig.Params().Len() - 1
190 for i, argtype := range argtypes[:nnormals] {
191 f.assign(sig.Params().At(i).Type(), argtype)
192 }
193
194 tElem := sig.Params().At(nnormals).Type().(*types.Slice).Elem()
195 for i := nnormals; i < len(argtypes); i++ {
196 f.assign(tElem, argtypes[i])
197 }
198 }
199 }
200
201
202 func (f *Finder) builtin(obj *types.Builtin, sig *types.Signature, args []ast.Expr) {
203 switch obj.Name() {
204 case "make", "new":
205 for i, arg := range args {
206 if i == 0 && f.info.Types[arg].IsType() {
207 continue
208 }
209 f.expr(arg)
210 }
211
212 case "append":
213 s := f.expr(args[0])
214 if _, ok := args[len(args)-1].(*ast.Ellipsis); ok && len(args) == 2 {
215
216 f.expr(args[1])
217 } else {
218
219 tElem := typeparams.CoreType(s).(*types.Slice).Elem()
220 for _, arg := range args[1:] {
221 f.assign(tElem, f.expr(arg))
222 }
223 }
224
225 case "delete":
226 m := f.expr(args[0])
227 k := f.expr(args[1])
228 f.assign(typeparams.CoreType(m).(*types.Map).Key(), k)
229
230 default:
231
232 f.call(sig, args)
233 }
234 }
235
236 func (f *Finder) extract(tuple types.Type, i int) types.Type {
237 if tuple, ok := tuple.(*types.Tuple); ok && i < tuple.Len() {
238 return tuple.At(i).Type()
239 }
240 return tInvalid
241 }
242
243 func (f *Finder) valueSpec(spec *ast.ValueSpec) {
244 var T types.Type
245 if spec.Type != nil {
246 T = f.info.Types[spec.Type].Type
247 }
248 switch len(spec.Values) {
249 case len(spec.Names):
250 for _, value := range spec.Values {
251 v := f.expr(value)
252 if T != nil {
253 f.assign(T, v)
254 }
255 }
256
257 case 1:
258 tuple := f.exprN(spec.Values[0])
259 for i := range spec.Names {
260 if T != nil {
261 f.assign(T, f.extract(tuple, i))
262 }
263 }
264 }
265 }
266
267
268
269
270
271
272
273
274
275 func (f *Finder) assign(lhs, rhs types.Type) {
276 if types.Identical(lhs, rhs) {
277 return
278 }
279 if !types.IsInterface(lhs) {
280 return
281 }
282
283 if f.msetcache.MethodSet(lhs).Len() == 0 {
284 return
285 }
286 if f.msetcache.MethodSet(rhs).Len() == 0 {
287 return
288 }
289
290 f.Result[Constraint{lhs, rhs}] = true
291 }
292
293
294
295 func (f *Finder) typeAssert(I, T types.Type) {
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 if types.AssignableTo(T, I) {
311 f.assign(I, T)
312 }
313 }
314
315
316 func (f *Finder) compare(x, y types.Type) {
317 if types.AssignableTo(x, y) {
318 f.assign(y, x)
319 } else if types.AssignableTo(y, x) {
320 f.assign(x, y)
321 }
322 }
323
324
325
326 func (f *Finder) expr(e ast.Expr) types.Type {
327 tv := f.info.Types[e]
328 if tv.Value != nil {
329 return tv.Type
330 }
331
332
333
334 switch e := e.(type) {
335 case *ast.BadExpr, *ast.BasicLit:
336
337
338 case *ast.Ident:
339
340 if obj, ok := f.info.Uses[e]; ok {
341 return obj.Type()
342 }
343 if e.Name == "_" {
344 return tInvalid
345 }
346 panic("undefined ident: " + e.Name)
347
348 case *ast.Ellipsis:
349 if e.Elt != nil {
350 f.expr(e.Elt)
351 }
352
353 case *ast.FuncLit:
354 saved := f.sig
355 f.sig = tv.Type.(*types.Signature)
356 f.stmt(e.Body)
357 f.sig = saved
358
359 case *ast.CompositeLit:
360 switch T := typeparams.CoreType(typeparams.Deref(tv.Type)).(type) {
361 case *types.Struct:
362 for i, elem := range e.Elts {
363 if kv, ok := elem.(*ast.KeyValueExpr); ok {
364 f.assign(f.info.Uses[kv.Key.(*ast.Ident)].Type(), f.expr(kv.Value))
365 } else {
366 f.assign(T.Field(i).Type(), f.expr(elem))
367 }
368 }
369
370 case *types.Map:
371 for _, elem := range e.Elts {
372 elem := elem.(*ast.KeyValueExpr)
373 f.assign(T.Key(), f.expr(elem.Key))
374 f.assign(T.Elem(), f.expr(elem.Value))
375 }
376
377 case *types.Array, *types.Slice:
378 tElem := T.(interface {
379 Elem() types.Type
380 }).Elem()
381 for _, elem := range e.Elts {
382 if kv, ok := elem.(*ast.KeyValueExpr); ok {
383
384 f.assign(tElem, f.expr(kv.Value))
385 } else {
386 f.assign(tElem, f.expr(elem))
387 }
388 }
389
390 default:
391 panic(fmt.Sprintf("unexpected composite literal type %T: %v", tv.Type, tv.Type.String()))
392 }
393
394 case *ast.ParenExpr:
395 f.expr(e.X)
396
397 case *ast.SelectorExpr:
398 if _, ok := f.info.Selections[e]; ok {
399 f.expr(e.X)
400 } else {
401 return f.info.Uses[e.Sel].Type()
402 }
403
404 case *ast.IndexExpr:
405 if instance(f.info, e.X) {
406
407 } else {
408
409 x := f.expr(e.X)
410 i := f.expr(e.Index)
411 if ux, ok := typeparams.CoreType(x).(*types.Map); ok {
412 f.assign(ux.Key(), i)
413 }
414 }
415
416 case *ast.IndexListExpr:
417
418
419 case *ast.SliceExpr:
420 f.expr(e.X)
421 if e.Low != nil {
422 f.expr(e.Low)
423 }
424 if e.High != nil {
425 f.expr(e.High)
426 }
427 if e.Max != nil {
428 f.expr(e.Max)
429 }
430
431 case *ast.TypeAssertExpr:
432 x := f.expr(e.X)
433 f.typeAssert(x, f.info.Types[e.Type].Type)
434
435 case *ast.CallExpr:
436 if tvFun := f.info.Types[e.Fun]; tvFun.IsType() {
437
438 arg0 := f.expr(e.Args[0])
439 f.assign(tvFun.Type, arg0)
440 } else {
441
442
443
444
445
446 if s, ok := ast.Unparen(e.Fun).(*ast.SelectorExpr); ok {
447 if obj, ok := f.info.Uses[s.Sel].(*types.Builtin); ok && obj.Pkg().Path() == "unsafe" {
448 sig := f.info.Types[e.Fun].Type.(*types.Signature)
449 f.call(sig, e.Args)
450 return tv.Type
451 }
452 }
453
454
455 if id, ok := ast.Unparen(e.Fun).(*ast.Ident); ok {
456 if obj, ok := f.info.Uses[id].(*types.Builtin); ok {
457 sig := f.info.Types[id].Type.(*types.Signature)
458 f.builtin(obj, sig, e.Args)
459 return tv.Type
460 }
461 }
462
463
464 f.call(typeparams.CoreType(f.expr(e.Fun)).(*types.Signature), e.Args)
465 }
466
467 case *ast.StarExpr:
468 f.expr(e.X)
469
470 case *ast.UnaryExpr:
471 f.expr(e.X)
472
473 case *ast.BinaryExpr:
474 x := f.expr(e.X)
475 y := f.expr(e.Y)
476 if e.Op == token.EQL || e.Op == token.NEQ {
477 f.compare(x, y)
478 }
479
480 case *ast.KeyValueExpr:
481 f.expr(e.Key)
482 f.expr(e.Value)
483
484 case *ast.ArrayType,
485 *ast.StructType,
486 *ast.FuncType,
487 *ast.InterfaceType,
488 *ast.MapType,
489 *ast.ChanType:
490 panic(e)
491 }
492
493 if tv.Type == nil {
494 panic(fmt.Sprintf("no type for %T", e))
495 }
496
497 return tv.Type
498 }
499
500 func (f *Finder) stmt(s ast.Stmt) {
501 switch s := s.(type) {
502 case *ast.BadStmt,
503 *ast.EmptyStmt,
504 *ast.BranchStmt:
505
506
507 case *ast.DeclStmt:
508 d := s.Decl.(*ast.GenDecl)
509 if d.Tok == token.VAR {
510 for _, spec := range d.Specs {
511 f.valueSpec(spec.(*ast.ValueSpec))
512 }
513 }
514
515 case *ast.LabeledStmt:
516 f.stmt(s.Stmt)
517
518 case *ast.ExprStmt:
519 f.expr(s.X)
520
521 case *ast.SendStmt:
522 ch := f.expr(s.Chan)
523 val := f.expr(s.Value)
524 f.assign(typeparams.CoreType(ch).(*types.Chan).Elem(), val)
525
526 case *ast.IncDecStmt:
527 f.expr(s.X)
528
529 case *ast.AssignStmt:
530 switch s.Tok {
531 case token.ASSIGN, token.DEFINE:
532
533 var rhsTuple types.Type
534 if len(s.Lhs) != len(s.Rhs) {
535 rhsTuple = f.exprN(s.Rhs[0])
536 }
537 for i := range s.Lhs {
538 var lhs, rhs types.Type
539 if rhsTuple == nil {
540 rhs = f.expr(s.Rhs[i])
541 } else {
542 rhs = f.extract(rhsTuple, i)
543 }
544
545 if id, ok := s.Lhs[i].(*ast.Ident); ok {
546 if id.Name != "_" {
547 if obj, ok := f.info.Defs[id]; ok {
548 lhs = obj.Type()
549 }
550 }
551 }
552 if lhs == nil {
553 lhs = f.expr(s.Lhs[i])
554 }
555 f.assign(lhs, rhs)
556 }
557
558 default:
559
560 f.expr(s.Lhs[0])
561 f.expr(s.Rhs[0])
562 }
563
564 case *ast.GoStmt:
565 f.expr(s.Call)
566
567 case *ast.DeferStmt:
568 f.expr(s.Call)
569
570 case *ast.ReturnStmt:
571 formals := f.sig.Results()
572 switch len(s.Results) {
573 case formals.Len():
574 for i, result := range s.Results {
575 f.assign(formals.At(i).Type(), f.expr(result))
576 }
577
578 case 1:
579 tuple := f.exprN(s.Results[0])
580 for i := 0; i < formals.Len(); i++ {
581 f.assign(formals.At(i).Type(), f.extract(tuple, i))
582 }
583 }
584
585 case *ast.SelectStmt:
586 f.stmt(s.Body)
587
588 case *ast.BlockStmt:
589 for _, s := range s.List {
590 f.stmt(s)
591 }
592
593 case *ast.IfStmt:
594 if s.Init != nil {
595 f.stmt(s.Init)
596 }
597 f.expr(s.Cond)
598 f.stmt(s.Body)
599 if s.Else != nil {
600 f.stmt(s.Else)
601 }
602
603 case *ast.SwitchStmt:
604 if s.Init != nil {
605 f.stmt(s.Init)
606 }
607 var tag types.Type = tUntypedBool
608 if s.Tag != nil {
609 tag = f.expr(s.Tag)
610 }
611 for _, cc := range s.Body.List {
612 cc := cc.(*ast.CaseClause)
613 for _, cond := range cc.List {
614 f.compare(tag, f.info.Types[cond].Type)
615 }
616 for _, s := range cc.Body {
617 f.stmt(s)
618 }
619 }
620
621 case *ast.TypeSwitchStmt:
622 if s.Init != nil {
623 f.stmt(s.Init)
624 }
625 var I types.Type
626 switch ass := s.Assign.(type) {
627 case *ast.ExprStmt:
628 I = f.expr(ast.Unparen(ass.X).(*ast.TypeAssertExpr).X)
629 case *ast.AssignStmt:
630 I = f.expr(ast.Unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X)
631 }
632 for _, cc := range s.Body.List {
633 cc := cc.(*ast.CaseClause)
634 for _, cond := range cc.List {
635 tCase := f.info.Types[cond].Type
636 if tCase != tUntypedNil {
637 f.typeAssert(I, tCase)
638 }
639 }
640 for _, s := range cc.Body {
641 f.stmt(s)
642 }
643 }
644
645 case *ast.CommClause:
646 if s.Comm != nil {
647 f.stmt(s.Comm)
648 }
649 for _, s := range s.Body {
650 f.stmt(s)
651 }
652
653 case *ast.ForStmt:
654 if s.Init != nil {
655 f.stmt(s.Init)
656 }
657 if s.Cond != nil {
658 f.expr(s.Cond)
659 }
660 if s.Post != nil {
661 f.stmt(s.Post)
662 }
663 f.stmt(s.Body)
664
665 case *ast.RangeStmt:
666 x := f.expr(s.X)
667
668 if s.Tok == token.ASSIGN {
669 if s.Key != nil {
670 k := f.expr(s.Key)
671 var xelem types.Type
672
673
674 switch ux := typeparams.CoreType(x).(type) {
675 case *types.Chan:
676 xelem = ux.Elem()
677 case *types.Map:
678 xelem = ux.Key()
679 }
680 if xelem != nil {
681 f.assign(k, xelem)
682 }
683 }
684 if s.Value != nil {
685 val := f.expr(s.Value)
686 var xelem types.Type
687
688
689 switch ux := typeparams.CoreType(x).(type) {
690 case *types.Array:
691 xelem = ux.Elem()
692 case *types.Map:
693 xelem = ux.Elem()
694 case *types.Pointer:
695 xelem = typeparams.CoreType(typeparams.Deref(ux)).(*types.Array).Elem()
696 case *types.Slice:
697 xelem = ux.Elem()
698 }
699 if xelem != nil {
700 f.assign(val, xelem)
701 }
702 }
703 }
704 f.stmt(s.Body)
705
706 default:
707 panic(s)
708 }
709 }
710
711
712
713 func instance(info *types.Info, expr ast.Expr) bool {
714 var id *ast.Ident
715 switch x := expr.(type) {
716 case *ast.Ident:
717 id = x
718 case *ast.SelectorExpr:
719 id = x.Sel
720 default:
721 return false
722 }
723 _, ok := info.Instances[id]
724 return ok
725 }
726
View as plain text