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