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