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