Source file
src/go/types/interface.go
1
2
3
4
5 package types
6
7 import (
8 "go/ast"
9 "go/token"
10 )
11
12
13
14
15
16 type Interface struct {
17 check *Checker
18 obj *TypeName
19 methods []*Func
20 embeddeds []Type
21 embedPos *[]token.Pos
22 implicit bool
23 complete bool
24
25 tset *_TypeSet
26 }
27
28
29 func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(t.check, token.NoPos, t) }
30
31
32 var emptyInterface = Interface{complete: true, tset: &topTypeSet}
33
34
35
36
37
38
39 func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
40 tnames := make([]Type, len(embeddeds))
41 for i, t := range embeddeds {
42 tnames[i] = t
43 }
44 return NewInterfaceType(methods, tnames)
45 }
46
47
48
49
50
51
52
53 func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
54 if len(methods) == 0 && len(embeddeds) == 0 {
55 return &emptyInterface
56 }
57
58
59 typ := (*Checker)(nil).newInterface()
60 for _, m := range methods {
61 if sig := m.typ.(*Signature); sig.recv == nil {
62 sig.recv = NewVar(m.pos, m.pkg, "", typ)
63 }
64 }
65
66
67 sortMethods(methods)
68
69 typ.methods = methods
70 typ.embeddeds = embeddeds
71 typ.complete = true
72
73 return typ
74 }
75
76
77 func (check *Checker) newInterface() *Interface {
78 typ := &Interface{check: check}
79 if check != nil {
80 check.needsCleanup(typ)
81 }
82 return typ
83 }
84
85
86
87
88
89 func (t *Interface) MarkImplicit() {
90 t.implicit = true
91 }
92
93
94 func (t *Interface) NumExplicitMethods() int { return len(t.methods) }
95
96
97
98 func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }
99
100
101 func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }
102
103
104
105
106
107 func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname }
108
109
110 func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] }
111
112
113 func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() }
114
115
116
117 func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) }
118
119
120 func (t *Interface) Empty() bool { return t.typeSet().IsAll() }
121
122
123 func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable(nil) }
124
125
126
127 func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() }
128
129
130 func (t *Interface) IsImplicit() bool { return t.implicit }
131
132
133
134
135
136
137
138
139 func (t *Interface) Complete() *Interface {
140 if !t.complete {
141 t.complete = true
142 }
143 t.typeSet()
144 return t
145 }
146
147 func (t *Interface) Underlying() Type { return t }
148 func (t *Interface) String() string { return TypeString(t, nil) }
149
150
151
152
153 func (t *Interface) cleanup() {
154 t.check = nil
155 t.embedPos = nil
156 }
157
158 func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
159 addEmbedded := func(pos token.Pos, typ Type) {
160 ityp.embeddeds = append(ityp.embeddeds, typ)
161 if ityp.embedPos == nil {
162 ityp.embedPos = new([]token.Pos)
163 }
164 *ityp.embedPos = append(*ityp.embedPos, pos)
165 }
166
167 for _, f := range iface.Methods.List {
168 if len(f.Names) == 0 {
169 addEmbedded(f.Type.Pos(), parseUnion(check, f.Type))
170 continue
171 }
172
173
174
175 name := f.Names[0]
176 if name.Name == "_" {
177 check.errorf(name, _BlankIfaceMethod, "invalid method name _")
178 continue
179 }
180
181 typ := check.typ(f.Type)
182 sig, _ := typ.(*Signature)
183 if sig == nil {
184 if typ != Typ[Invalid] {
185 check.invalidAST(f.Type, "%s is not a method signature", typ)
186 }
187 continue
188 }
189
190
191
192
193 if sig.tparams != nil {
194 var at positioner = f.Type
195 if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil {
196 at = ftyp.TypeParams
197 }
198 check.errorf(at, _InvalidMethodTypeParams, "methods cannot have type parameters")
199 }
200
201
202 var recvTyp Type = ityp
203 if def != nil {
204 recvTyp = def
205 }
206 sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp)
207
208 m := NewFunc(name.Pos(), check.pkg, name.Name, sig)
209 check.recordDef(name, m)
210 ityp.methods = append(ityp.methods, m)
211 }
212
213
214
215 ityp.complete = true
216
217 if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 {
218
219 ityp.tset = &topTypeSet
220 return
221 }
222
223
224 sortMethods(ityp.methods)
225
226
227
228
229
230 check.later(func() {
231 computeInterfaceTypeSet(check, iface.Pos(), ityp)
232 }).describef(iface, "compute type set for %s", ityp)
233 }
234
View as plain text