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 check.errorf(obj, DuplicateDecl, "%s redeclared in this block", obj.Name())
197 check.reportAltDecl(alt)
198 })
199
200 if recvPar != nil {
201
202
203
204 var recv *Var
205 switch len(recvList) {
206 case 0:
207
208 recv = NewParam(nopos, nil, "", Typ[Invalid])
209 default:
210
211 check.error(recvList[len(recvList)-1], InvalidRecv, "method has multiple receivers")
212 fallthrough
213 case 1:
214 recv = recvList[0]
215 }
216 sig.recv = recv
217
218
219
220 check.later(func() {
221
222 rtyp, _ := deref(recv.typ)
223 atyp := Unalias(rtyp)
224 if !isValid(atyp) {
225 return
226 }
227
228
229
230 switch T := atyp.(type) {
231 case *Named:
232
233
234 if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
235 check.errorf(recv, InvalidRecv, "cannot define new methods on instantiated type %s", rtyp)
236 break
237 }
238 if T.obj.pkg != check.pkg {
239 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
240 break
241 }
242 var cause string
243 switch u := T.under().(type) {
244 case *Basic:
245
246 if u.kind == UnsafePointer {
247 cause = "unsafe.Pointer"
248 }
249 case *Pointer, *Interface:
250 cause = "pointer or interface type"
251 case *TypeParam:
252
253
254 unreachable()
255 }
256 if cause != "" {
257 check.errorf(recv, InvalidRecv, "invalid receiver type %s (%s)", rtyp, cause)
258 }
259 case *Basic:
260 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
261 default:
262 check.errorf(recv, InvalidRecv, "invalid receiver type %s", recv.typ)
263 }
264 }).describef(recv, "validate receiver %s", recv)
265 }
266
267 sig.params = NewTuple(params...)
268 sig.results = NewTuple(results...)
269 sig.variadic = variadic
270 }
271
272
273
274 func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool, scopePos token.Pos) (params []*Var, variadic bool) {
275 if list == nil {
276 return
277 }
278
279 var named, anonymous bool
280 for i, field := range list.List {
281 ftype := field.Type
282 if t, _ := ftype.(*ast.Ellipsis); t != nil {
283 ftype = t.Elt
284 if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 {
285 variadic = true
286 } else {
287 check.softErrorf(t, MisplacedDotDotDot, "can only use ... with final parameter in list")
288
289 }
290 }
291 typ := check.varType(ftype)
292
293
294 if len(field.Names) > 0 {
295
296 for _, name := range field.Names {
297 if name.Name == "" {
298 check.error(name, InvalidSyntaxTree, "anonymous parameter")
299
300 }
301 par := NewParam(name.Pos(), check.pkg, name.Name, typ)
302 check.declare(scope, name, par, scopePos)
303 params = append(params, par)
304 }
305 named = true
306 } else {
307
308 par := NewParam(ftype.Pos(), check.pkg, "", typ)
309 check.recordImplicit(field, par)
310 params = append(params, par)
311 anonymous = true
312 }
313 }
314
315 if named && anonymous {
316 check.error(list, InvalidSyntaxTree, "list contains both named and anonymous parameters")
317
318 }
319
320
321
322
323 if variadic {
324 last := params[len(params)-1]
325 last.typ = &Slice{elem: last.typ}
326 check.recordTypeAndValue(list.List[len(list.List)-1].Type, typexpr, last.typ, nil)
327 }
328
329 return
330 }
331
View as plain text