Source file
src/go/types/signature.go
1
2
3
4
5 package types
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/token"
11 . "internal/types/errors"
12 )
13
14
15
16
17
18
19 type Signature struct {
20
21
22
23
24 rparams *TypeParamList
25 tparams *TypeParamList
26 scope *Scope
27 recv *Var
28 params *Tuple
29 results *Tuple
30 variadic bool
31 }
32
33
34
35
36
37
38
39 func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
40 return NewSignatureType(recv, nil, nil, params, results, variadic)
41 }
42
43
44
45
46
47
48
49 func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
50 if variadic {
51 n := params.Len()
52 if n == 0 {
53 panic("variadic function must have at least one parameter")
54 }
55 core := coreString(params.At(n - 1).typ)
56 if _, ok := core.(*Slice); !ok && !isString(core) {
57 panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
58 }
59 }
60 sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}
61 if len(recvTypeParams) != 0 {
62 if recv == nil {
63 panic("function with receiver type parameters must have a receiver")
64 }
65 sig.rparams = bindTParams(recvTypeParams)
66 }
67 if len(typeParams) != 0 {
68 if recv != nil {
69 panic("function with type parameters cannot have a receiver")
70 }
71 sig.tparams = bindTParams(typeParams)
72 }
73 return sig
74 }
75
76
77
78
79
80
81
82 func (s *Signature) Recv() *Var { return s.recv }
83
84
85 func (s *Signature) TypeParams() *TypeParamList { return s.tparams }
86
87
88 func (s *Signature) RecvTypeParams() *TypeParamList { return s.rparams }
89
90
91 func (s *Signature) Params() *Tuple { return s.params }
92
93
94 func (s *Signature) Results() *Tuple { return s.results }
95
96
97 func (s *Signature) Variadic() bool { return s.variadic }
98
99 func (t *Signature) Underlying() Type { return t }
100 func (t *Signature) String() string { return TypeString(t, nil) }
101
102
103
104
105
106 func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) {
107 check.openScope(ftyp, "function")
108 check.scope.isFunc = true
109 check.recordScope(ftyp, check.scope)
110 sig.scope = check.scope
111 defer check.closeScope()
112
113 if recvPar != nil && len(recvPar.List) > 0 {
114
115
116
117 _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
118 if len(rparams) > 0 {
119
120
121 scopePos := ftyp.Params.Pos()
122 tparams := check.declareTypeParams(nil, rparams, scopePos)
123 sig.rparams = bindTParams(tparams)
124
125
126
127
128
129
130
131 for i, p := range rparams {
132 if p.Name == "_" {
133 if check.recvTParamMap == nil {
134 check.recvTParamMap = make(map[*ast.Ident]*TypeParam)
135 }
136 check.recvTParamMap[p] = tparams[i]
137 }
138 }
139
140
141 var recvTParams []*TypeParam
142 if rname != nil {
143
144
145
146
147 if recv := asNamed(check.genericType(rname, nil)); recv != nil {
148 recvTParams = recv.TypeParams().list()
149 }
150 }
151
152 if len(tparams) == len(recvTParams) {
153 smap := makeRenameMap(recvTParams, tparams)
154 for i, tpar := range tparams {
155 recvTPar := recvTParams[i]
156 check.mono.recordCanon(tpar, recvTPar)
157
158
159
160 tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil, check.context())
161 }
162 } else if len(tparams) < len(recvTParams) {
163
164
165
166
167 got := measure(len(tparams), "type parameter")
168 check.errorf(recvPar, BadRecv, "got %s, but receiver base type declares %d", got, len(recvTParams))
169 }
170 }
171 }
172
173 if ftyp.TypeParams != nil {
174 check.collectTypeParams(&sig.tparams, ftyp.TypeParams)
175
176
177
178 if recvPar != nil {
179 check.error(ftyp.TypeParams, InvalidMethodTypeParams, "methods cannot have type parameters")
180 }
181 }
182
183
184
185
186
187
188
189
190 scope := NewScope(check.scope, nopos, nopos, "function body (temp. scope)")
191 scopePos := ftyp.End()
192 recvList, _ := check.collectParams(scope, recvPar, false, scopePos)
193 params, variadic := check.collectParams(scope, ftyp.Params, true, scopePos)
194 results, _ := check.collectParams(scope, ftyp.Results, false, scopePos)
195 scope.squash(func(obj, alt Object) {
196 err := check.newError(DuplicateDecl)
197 err.addf(obj, "%s redeclared in this block", obj.Name())
198 err.addAltDecl(alt)
199 err.report()
200 })
201
202 if recvPar != nil {
203
204
205
206 var recv *Var
207 switch len(recvList) {
208 case 0:
209
210 recv = NewParam(nopos, nil, "", Typ[Invalid])
211 default:
212
213 check.error(recvList[len(recvList)-1], InvalidRecv, "method has multiple receivers")
214 fallthrough
215 case 1:
216 recv = recvList[0]
217 }
218 sig.recv = recv
219
220
221
222 check.later(func() {
223
224 rtyp, _ := deref(recv.typ)
225 atyp := Unalias(rtyp)
226 if !isValid(atyp) {
227 return
228 }
229
230
231
232 switch T := atyp.(type) {
233 case *Named:
234
235
236 if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
237 check.errorf(recv, InvalidRecv, "cannot define new methods on instantiated type %s", rtyp)
238 break
239 }
240 if T.obj.pkg != check.pkg {
241 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
242 break
243 }
244 var cause string
245 switch u := T.under().(type) {
246 case *Basic:
247
248 if u.kind == UnsafePointer {
249 cause = "unsafe.Pointer"
250 }
251 case *Pointer, *Interface:
252 cause = "pointer or interface type"
253 case *TypeParam:
254
255
256 panic("unreachable")
257 }
258 if cause != "" {
259 check.errorf(recv, InvalidRecv, "invalid receiver type %s (%s)", rtyp, cause)
260 }
261 case *Basic:
262 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
263 default:
264 check.errorf(recv, InvalidRecv, "invalid receiver type %s", recv.typ)
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, scopePos token.Pos) (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.error(name, InvalidSyntaxTree, "anonymous parameter")
301
302 }
303 par := NewParam(name.Pos(), check.pkg, name.Name, typ)
304 check.declare(scope, name, par, scopePos)
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.error(list, InvalidSyntaxTree, "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