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