...
1
2
3
4
5 package typeparams
6
7 import (
8 "go/types"
9
10 "golang.org/x/tools/internal/aliases"
11 )
12
13
14
15
16
17
18 type Free struct {
19 seen map[types.Type]bool
20 }
21
22
23 func (w *Free) Has(typ types.Type) (res bool) {
24
25
26 if x, ok := w.seen[typ]; ok {
27 return x
28 }
29 if w.seen == nil {
30 w.seen = make(map[types.Type]bool)
31 }
32 w.seen[typ] = false
33 defer func() {
34 w.seen[typ] = res
35 }()
36
37 switch t := typ.(type) {
38 case nil, *types.Basic:
39 break
40
41 case *aliases.Alias:
42 return w.Has(aliases.Unalias(t))
43
44 case *types.Array:
45 return w.Has(t.Elem())
46
47 case *types.Slice:
48 return w.Has(t.Elem())
49
50 case *types.Struct:
51 for i, n := 0, t.NumFields(); i < n; i++ {
52 if w.Has(t.Field(i).Type()) {
53 return true
54 }
55 }
56
57 case *types.Pointer:
58 return w.Has(t.Elem())
59
60 case *types.Tuple:
61 n := t.Len()
62 for i := 0; i < n; i++ {
63 if w.Has(t.At(i).Type()) {
64 return true
65 }
66 }
67
68 case *types.Signature:
69
70
71
72
73
74
75
76 return w.Has(t.Params()) || w.Has(t.Results())
77
78 case *types.Interface:
79 for i, n := 0, t.NumMethods(); i < n; i++ {
80 if w.Has(t.Method(i).Type()) {
81 return true
82 }
83 }
84 terms, err := InterfaceTermSet(t)
85 if err != nil {
86 panic(err)
87 }
88 for _, term := range terms {
89 if w.Has(term.Type()) {
90 return true
91 }
92 }
93
94 case *types.Map:
95 return w.Has(t.Key()) || w.Has(t.Elem())
96
97 case *types.Chan:
98 return w.Has(t.Elem())
99
100 case *types.Named:
101 args := t.TypeArgs()
102
103 if params := t.TypeParams(); params.Len() > args.Len() {
104 return true
105 }
106 for i, n := 0, args.Len(); i < n; i++ {
107 if w.Has(args.At(i)) {
108 return true
109 }
110 }
111 return w.Has(t.Underlying())
112
113 case *types.TypeParam:
114 return true
115
116 default:
117 panic(t)
118 }
119
120 return false
121 }
122
View as plain text