1
2
3
4
5 package types2
6
7 import (
8 "cmd/compile/internal/syntax"
9 "fmt"
10 . "internal/types/errors"
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 NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature {
39 if variadic {
40 n := params.Len()
41 if n == 0 {
42 panic("variadic function must have at least one parameter")
43 }
44 core := coreString(params.At(n - 1).typ)
45 if _, ok := core.(*Slice); !ok && !isString(core) {
46 panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String()))
47 }
48 }
49 sig := &Signature{recv: recv, params: params, results: results, variadic: variadic}
50 if len(recvTypeParams) != 0 {
51 if recv == nil {
52 panic("function with receiver type parameters must have a receiver")
53 }
54 sig.rparams = bindTParams(recvTypeParams)
55 }
56 if len(typeParams) != 0 {
57 if recv != nil {
58 panic("function with type parameters cannot have a receiver")
59 }
60 sig.tparams = bindTParams(typeParams)
61 }
62 return sig
63 }
64
65
66
67
68
69
70
71 func (s *Signature) Recv() *Var { return s.recv }
72
73
74 func (s *Signature) TypeParams() *TypeParamList { return s.tparams }
75
76
77 func (s *Signature) RecvTypeParams() *TypeParamList { return s.rparams }
78
79
80 func (s *Signature) Params() *Tuple { return s.params }
81
82
83 func (s *Signature) Results() *Tuple { return s.results }
84
85
86 func (s *Signature) Variadic() bool { return s.variadic }
87
88 func (s *Signature) Underlying() Type { return s }
89 func (s *Signature) String() string { return TypeString(s, nil) }
90
91
92
93
94
95 func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []*syntax.Field, ftyp *syntax.FuncType) {
96 check.openScope(ftyp, "function")
97 check.scope.isFunc = true
98 check.recordScope(ftyp, check.scope)
99 sig.scope = check.scope
100 defer check.closeScope()
101
102
103 var recv *Var
104 var rparams *TypeParamList
105 if recvPar != nil {
106
107 scopePos := ftyp.Pos()
108 recv, rparams = check.collectRecv(recvPar, scopePos)
109 }
110
111
112 if tparams != nil {
113
114 check.collectTypeParams(&sig.tparams, tparams)
115 }
116
117
118 pnames, params, variadic := check.collectParams(ftyp.ParamList, true)
119 rnames, results, _ := check.collectParams(ftyp.ResultList, false)
120
121
122 scopePos := syntax.EndPos(ftyp)
123 if recv != nil && recv.name != "" {
124 check.declare(check.scope, recvPar.Name, recv, scopePos)
125 }
126 check.declareParams(pnames, params, scopePos)
127 check.declareParams(rnames, results, scopePos)
128
129 sig.recv = recv
130 sig.rparams = rparams
131 sig.params = NewTuple(params...)
132 sig.results = NewTuple(results...)
133 sig.variadic = variadic
134 }
135
136
137
138
139 func (check *Checker) collectRecv(rparam *syntax.Field, scopePos syntax.Pos) (recv *Var, recvTParamsList *TypeParamList) {
140
141
142
143
144
145
146 rptr, rbase, rtparams := check.unpackRecv(rparam.Type, true)
147
148
149 var recvType Type = Typ[Invalid]
150 if rtparams == nil {
151
152
153
154
155
156 recvType = check.varType(rparam.Type)
157 } else {
158
159 var baseType *Named
160 var cause string
161 if t := check.genericType(rbase, &cause); cause == "" {
162 baseType = asNamed(t)
163 } else {
164 check.errorf(rbase, InvalidRecv, "%s", cause)
165
166 }
167
168
169
170
171
172 recvTParams := make([]*TypeParam, len(rtparams))
173 for i, rparam := range rtparams {
174 tpar := check.declareTypeParam(rparam, scopePos)
175 recvTParams[i] = tpar
176
177
178
179 check.recordUse(rparam, tpar.obj)
180 check.recordTypeAndValue(rparam, typexpr, tpar, nil)
181 }
182 recvTParamsList = bindTParams(recvTParams)
183
184
185
186 if baseType != nil {
187 baseTParams := baseType.TypeParams().list()
188 if len(recvTParams) == len(baseTParams) {
189 smap := makeRenameMap(baseTParams, recvTParams)
190 for i, recvTPar := range recvTParams {
191 baseTPar := baseTParams[i]
192 check.mono.recordCanon(recvTPar, baseTPar)
193
194
195
196 recvTPar.bound = check.subst(recvTPar.obj.pos, baseTPar.bound, smap, nil, check.context())
197 }
198 } else {
199 got := measure(len(recvTParams), "type parameter")
200 check.errorf(rbase, BadRecv, "receiver declares %s, but receiver base type declares %d", got, len(baseTParams))
201 }
202
203
204
205 check.verifyVersionf(rbase, go1_18, "type instantiation")
206 targs := make([]Type, len(recvTParams))
207 for i, targ := range recvTParams {
208 targs[i] = targ
209 }
210 recvType = check.instance(rparam.Type.Pos(), baseType, targs, nil, check.context())
211 check.recordInstance(rbase, targs, recvType)
212
213
214 if rptr && isValid(recvType) {
215 recvType = NewPointer(recvType)
216 }
217
218 check.recordParenthesizedRecvTypes(rparam.Type, recvType)
219 }
220 }
221
222
223 if rname := rparam.Name; rname != nil && rname.Value != "" {
224
225 recv = NewParam(rname.Pos(), check.pkg, rname.Value, recvType)
226
227 } else {
228
229 recv = NewParam(rparam.Pos(), check.pkg, "", recvType)
230 check.recordImplicit(rparam, recv)
231 }
232
233
234
235 check.later(func() {
236 check.validRecv(recv, len(rtparams) != 0)
237 }).describef(recv, "validRecv(%s)", recv)
238
239 return
240 }
241
242
243
244
245
246
247
248
249
250
251
252 func (check *Checker) recordParenthesizedRecvTypes(expr syntax.Expr, typ Type) {
253 for {
254 check.recordTypeAndValue(expr, typexpr, typ, nil)
255 switch e := expr.(type) {
256 case *syntax.ParenExpr:
257 expr = e.X
258 case *syntax.Operation:
259 if e.Op == syntax.Mul && e.Y == nil {
260 expr = e.X
261
262
263 ptr, _ := typ.(*Pointer)
264 if ptr == nil {
265 return
266 }
267 typ = ptr.base
268 break
269 }
270 return
271 default:
272 return
273 }
274 }
275 }
276
277
278
279
280 func (check *Checker) collectParams(list []*syntax.Field, variadicOk bool) (names []*syntax.Name, params []*Var, variadic bool) {
281 if list == nil {
282 return
283 }
284
285 var named, anonymous bool
286
287 var typ Type
288 var prev syntax.Expr
289 for i, field := range list {
290 ftype := field.Type
291
292 if ftype != prev {
293 prev = ftype
294 if t, _ := ftype.(*syntax.DotsType); t != nil {
295 ftype = t.Elem
296 if variadicOk && i == len(list)-1 {
297 variadic = true
298 } else {
299 check.softErrorf(t, MisplacedDotDotDot, "can only use ... with final parameter in list")
300
301 }
302 }
303 typ = check.varType(ftype)
304 }
305
306
307 if field.Name != nil {
308
309 name := field.Name.Value
310 if name == "" {
311 check.error(field.Name, InvalidSyntaxTree, "anonymous parameter")
312
313 }
314 par := NewParam(field.Name.Pos(), check.pkg, name, typ)
315
316 names = append(names, field.Name)
317 params = append(params, par)
318 named = true
319 } else {
320
321 par := NewParam(field.Pos(), check.pkg, "", typ)
322 check.recordImplicit(field, par)
323 names = append(names, nil)
324 params = append(params, par)
325 anonymous = true
326 }
327 }
328
329 if named && anonymous {
330 check.error(list[0], InvalidSyntaxTree, "list contains both named and anonymous parameters")
331
332 }
333
334
335
336
337 if variadic {
338 last := params[len(params)-1]
339 last.typ = &Slice{elem: last.typ}
340 check.recordTypeAndValue(list[len(list)-1].Type, typexpr, last.typ, nil)
341 }
342
343 return
344 }
345
346
347 func (check *Checker) declareParams(names []*syntax.Name, params []*Var, scopePos syntax.Pos) {
348 for i, name := range names {
349 if name != nil && name.Value != "" {
350 check.declare(check.scope, name, params[i], scopePos)
351 }
352 }
353 }
354
355
356
357
358 func (check *Checker) validRecv(recv *Var, hasTypeParams bool) {
359
360 rtyp, _ := deref(recv.typ)
361 atyp := Unalias(rtyp)
362 if !isValid(atyp) {
363 return
364 }
365
366
367
368 switch T := atyp.(type) {
369 case *Named:
370
371
372
373
374 if T.TypeArgs() != nil && !hasTypeParams {
375 check.errorf(recv, InvalidRecv, "cannot define new methods on instantiated type %s", rtyp)
376 break
377 }
378 if T.obj.pkg != check.pkg {
379 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
380 break
381 }
382 var cause string
383 switch u := T.under().(type) {
384 case *Basic:
385
386 if u.kind == UnsafePointer {
387 cause = "unsafe.Pointer"
388 }
389 case *Pointer, *Interface:
390 cause = "pointer or interface type"
391 case *TypeParam:
392
393
394 panic("unreachable")
395 }
396 if cause != "" {
397 check.errorf(recv, InvalidRecv, "invalid receiver type %s (%s)", rtyp, cause)
398 }
399 case *Basic:
400 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
401 default:
402 check.errorf(recv, InvalidRecv, "invalid receiver type %s", recv.typ)
403 }
404 }
405
View as plain text