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