Source file
src/go/types/signature.go
1
2
3
4
5 package types
6
7 import (
8 "go/ast"
9 "go/token"
10 )
11
12
13
14
15
16
17 type Signature struct {
18
19
20
21
22 rparams *TypeParamList
23 tparams *TypeParamList
24 scope *Scope
25 recv *Var
26 params *Tuple
27 results *Tuple
28 variadic bool
29 }
30
31
32
33
34
35
36
37 func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
38 return NewSignatureType(recv, nil, nil, params, results, variadic)
39 }
40
41
42
43
44
45
46 func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
47 if variadic {
48 n := params.Len()
49 if n == 0 {
50 panic("variadic function must have at least one parameter")
51 }
52 if _, ok := params.At(n - 1).typ.(*Slice); !ok {
53 panic("variadic parameter must be of unnamed slice type")
54 }
55 }
56 sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}
57 if len(recvTypeParams) != 0 {
58 if recv == nil {
59 panic("function with receiver type parameters must have a receiver")
60 }
61 sig.rparams = bindTParams(recvTypeParams)
62 }
63 if len(typeParams) != 0 {
64 if recv != nil {
65 panic("function with type parameters cannot have a receiver")
66 }
67 sig.tparams = bindTParams(typeParams)
68 }
69 return sig
70 }
71
72
73
74
75
76
77
78 func (s *Signature) Recv() *Var { return s.recv }
79
80
81 func (s *Signature) TypeParams() *TypeParamList { return s.tparams }
82
83
84 func (s *Signature) RecvTypeParams() *TypeParamList { return s.rparams }
85
86
87 func (s *Signature) Params() *Tuple { return s.params }
88
89
90 func (s *Signature) Results() *Tuple { return s.results }
91
92
93 func (s *Signature) Variadic() bool { return s.variadic }
94
95 func (t *Signature) Underlying() Type { return t }
96 func (t *Signature) String() string { return TypeString(t, nil) }
97
98
99
100
101
102 func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) {
103 check.openScope(ftyp, "function")
104 check.scope.isFunc = true
105 check.recordScope(ftyp, check.scope)
106 sig.scope = check.scope
107 defer check.closeScope()
108
109 if recvPar != nil && len(recvPar.List) > 0 {
110
111
112
113 _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
114 if len(rparams) > 0 {
115 tparams := check.declareTypeParams(nil, rparams)
116 sig.rparams = bindTParams(tparams)
117
118
119
120
121
122
123
124 for i, p := range rparams {
125 if p.Name == "_" {
126 if check.recvTParamMap == nil {
127 check.recvTParamMap = make(map[*ast.Ident]*TypeParam)
128 }
129 check.recvTParamMap[p] = tparams[i]
130 }
131 }
132
133
134 var recvTParams []*TypeParam
135 if rname != nil {
136
137
138
139
140 if recv, _ := check.genericType(rname, nil).(*Named); recv != nil {
141 recvTParams = recv.TypeParams().list()
142 }
143 }
144
145 if len(tparams) == len(recvTParams) {
146 smap := makeRenameMap(recvTParams, tparams)
147 for i, tpar := range tparams {
148 recvTPar := recvTParams[i]
149 check.mono.recordCanon(tpar, recvTPar)
150
151
152
153 tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil)
154 }
155 } else if len(tparams) < len(recvTParams) {
156
157
158
159
160 got := measure(len(tparams), "type parameter")
161 check.errorf(recvPar, _BadRecv, "got %s, but receiver base type declares %d", got, len(recvTParams))
162 }
163 }
164 }
165
166 if ftyp.TypeParams != nil {
167 check.collectTypeParams(&sig.tparams, ftyp.TypeParams)
168
169
170
171 if recvPar != nil {
172 check.errorf(ftyp.TypeParams, _InvalidMethodTypeParams, "methods cannot have type parameters")
173 }
174 }
175
176
177
178
179 scope := NewScope(check.scope, token.NoPos, token.NoPos, "function body (temp. scope)")
180 recvList, _ := check.collectParams(scope, recvPar, false)
181 params, variadic := check.collectParams(scope, ftyp.Params, true)
182 results, _ := check.collectParams(scope, ftyp.Results, false)
183 scope.squash(func(obj, alt Object) {
184 check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name())
185 check.reportAltDecl(alt)
186 })
187
188 if recvPar != nil {
189
190
191
192 var recv *Var
193 switch len(recvList) {
194 case 0:
195
196 recv = NewParam(token.NoPos, nil, "", Typ[Invalid])
197 default:
198
199 check.error(recvList[len(recvList)-1], _InvalidRecv, "method must have exactly one receiver")
200 fallthrough
201 case 1:
202 recv = recvList[0]
203 }
204 sig.recv = recv
205
206
207
208 check.later(func() {
209 rtyp, _ := deref(recv.typ)
210
211
212
213 if rtyp != Typ[Invalid] {
214 var err string
215 switch T := rtyp.(type) {
216 case *Named:
217 T.resolve(check.bestContext(nil))
218
219
220 if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
221 check.errorf(recv, _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
222 break
223 }
224
225
226
227 if T.obj.pkg != check.pkg {
228 err = "type not defined in this package"
229 if compilerErrorMessages {
230 check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
231 err = ""
232 }
233 } else {
234
235
236
237
238 underIs(T, func(u Type) bool {
239 switch u := u.(type) {
240 case *Basic:
241
242 if u.kind == UnsafePointer {
243 err = "unsafe.Pointer"
244 return false
245 }
246 case *Pointer, *Interface:
247 err = "pointer or interface type"
248 return false
249 }
250 return true
251 })
252 }
253 case *Basic:
254 err = "basic or unnamed type"
255 if compilerErrorMessages {
256 check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
257 err = ""
258 }
259 default:
260 check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
261 }
262 if err != "" {
263 check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
264 }
265 }
266 }).describef(recv, "validate receiver %s", recv)
267 }
268
269 sig.params = NewTuple(params...)
270 sig.results = NewTuple(results...)
271 sig.variadic = variadic
272 }
273
274
275
276 func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
277 if list == nil {
278 return
279 }
280
281 var named, anonymous bool
282 for i, field := range list.List {
283 ftype := field.Type
284 if t, _ := ftype.(*ast.Ellipsis); t != nil {
285 ftype = t.Elt
286 if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 {
287 variadic = true
288 } else {
289 check.softErrorf(t, _MisplacedDotDotDot, "can only use ... with final parameter in list")
290
291 }
292 }
293 typ := check.varType(ftype)
294
295
296 if len(field.Names) > 0 {
297
298 for _, name := range field.Names {
299 if name.Name == "" {
300 check.invalidAST(name, "anonymous parameter")
301
302 }
303 par := NewParam(name.Pos(), check.pkg, name.Name, typ)
304 check.declare(scope, name, par, scope.pos)
305 params = append(params, par)
306 }
307 named = true
308 } else {
309
310 par := NewParam(ftype.Pos(), check.pkg, "", typ)
311 check.recordImplicit(field, par)
312 params = append(params, par)
313 anonymous = true
314 }
315 }
316
317 if named && anonymous {
318 check.invalidAST(list, "list contains both named and anonymous parameters")
319
320 }
321
322
323
324
325 if variadic {
326 last := params[len(params)-1]
327 last.typ = &Slice{elem: last.typ}
328 check.recordTypeAndValue(list.List[len(list.List)-1].Type, typexpr, last.typ, nil)
329 }
330
331 return
332 }
333
View as plain text