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 if recvPar != nil {
103
104
105
106 _, rname, rparams := check.unpackRecv(recvPar.Type, true)
107 if len(rparams) > 0 {
108
109
110 scopePos := ftyp.Pos()
111 tparams := make([]*TypeParam, len(rparams))
112 for i, rparam := range rparams {
113 tparams[i] = check.declareTypeParam(rparam, scopePos)
114 }
115 sig.rparams = bindTParams(tparams)
116
117
118
119
120
121
122
123 for i, p := range rparams {
124 if p.Value == "_" {
125 if check.recvTParamMap == nil {
126 check.recvTParamMap = make(map[*syntax.Name]*TypeParam)
127 }
128 check.recvTParamMap[p] = tparams[i]
129 }
130 }
131
132
133 var recvTParams []*TypeParam
134 if rname != nil {
135
136
137
138
139 if recv := asNamed(check.genericType(rname, nil)); recv != nil {
140 recvTParams = recv.TypeParams().list()
141 }
142 }
143
144 if len(tparams) == len(recvTParams) {
145 smap := makeRenameMap(recvTParams, tparams)
146 for i, tpar := range tparams {
147 recvTPar := recvTParams[i]
148 check.mono.recordCanon(tpar, recvTPar)
149
150
151
152 tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil, check.context())
153 }
154 } else if len(tparams) < len(recvTParams) {
155
156
157
158
159 got := measure(len(tparams), "type parameter")
160 check.errorf(recvPar, BadRecv, "got %s, but receiver base type declares %d", got, len(recvTParams))
161 }
162 }
163 }
164
165 if tparams != nil {
166
167 check.collectTypeParams(&sig.tparams, tparams)
168 }
169
170
171
172
173
174
175
176
177 scope := NewScope(check.scope, nopos, nopos, "function body (temp. scope)")
178 scopePos := syntax.EndPos(ftyp)
179 var recvList []*Var
180 if recvPar != nil {
181 recvList, _ = check.collectParams(scope, []*syntax.Field{recvPar}, false, scopePos)
182 }
183 params, variadic := check.collectParams(scope, ftyp.ParamList, true, scopePos)
184 results, _ := check.collectParams(scope, ftyp.ResultList, false, scopePos)
185 scope.Squash(func(obj, alt Object) {
186 err := check.newError(DuplicateDecl)
187 err.addf(obj, "%s redeclared in this block", obj.Name())
188 err.addAltDecl(alt)
189 err.report()
190 })
191
192 if recvPar != nil {
193
194
195
196 var recv *Var
197 switch len(recvList) {
198 case 0:
199
200 recv = NewParam(nopos, nil, "", Typ[Invalid])
201 default:
202
203 check.error(recvList[len(recvList)-1].Pos(), InvalidRecv, "method must have exactly one receiver")
204 fallthrough
205 case 1:
206 recv = recvList[0]
207 }
208 sig.recv = recv
209
210
211
212 check.later(func() {
213
214 rtyp, _ := deref(recv.typ)
215 atyp := Unalias(rtyp)
216 if !isValid(atyp) {
217 return
218 }
219
220
221
222 switch T := atyp.(type) {
223 case *Named:
224
225
226 if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
227 check.errorf(recv, InvalidRecv, "cannot define new methods on instantiated type %s", rtyp)
228 break
229 }
230 if T.obj.pkg != check.pkg {
231 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
232 break
233 }
234 var cause string
235 switch u := T.under().(type) {
236 case *Basic:
237
238 if u.kind == UnsafePointer {
239 cause = "unsafe.Pointer"
240 }
241 case *Pointer, *Interface:
242 cause = "pointer or interface type"
243 case *TypeParam:
244
245
246 panic("unreachable")
247 }
248 if cause != "" {
249 check.errorf(recv, InvalidRecv, "invalid receiver type %s (%s)", rtyp, cause)
250 }
251 case *Basic:
252 check.errorf(recv, InvalidRecv, "cannot define new methods on non-local type %s", rtyp)
253 default:
254 check.errorf(recv, InvalidRecv, "invalid receiver type %s", recv.typ)
255 }
256 }).describef(recv, "validate receiver %s", recv)
257 }
258
259 sig.params = NewTuple(params...)
260 sig.results = NewTuple(results...)
261 sig.variadic = variadic
262 }
263
264
265
266 func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, variadicOk bool, scopePos syntax.Pos) (params []*Var, variadic bool) {
267 if list == nil {
268 return
269 }
270
271 var named, anonymous bool
272
273 var typ Type
274 var prev syntax.Expr
275 for i, field := range list {
276 ftype := field.Type
277
278 if ftype != prev {
279 prev = ftype
280 if t, _ := ftype.(*syntax.DotsType); t != nil {
281 ftype = t.Elem
282 if variadicOk && i == len(list)-1 {
283 variadic = true
284 } else {
285 check.softErrorf(t, MisplacedDotDotDot, "can only use ... with final parameter in list")
286
287 }
288 }
289 typ = check.varType(ftype)
290 }
291
292
293 if field.Name != nil {
294
295 name := field.Name.Value
296 if name == "" {
297 check.error(field.Name, InvalidSyntaxTree, "anonymous parameter")
298
299 }
300 par := NewParam(field.Name.Pos(), check.pkg, name, typ)
301 check.declare(scope, field.Name, par, scopePos)
302 params = append(params, par)
303 named = true
304 } else {
305
306 par := NewParam(field.Pos(), check.pkg, "", typ)
307 check.recordImplicit(field, par)
308 params = append(params, par)
309 anonymous = true
310 }
311 }
312
313 if named && anonymous {
314 check.error(list[0], InvalidSyntaxTree, "list contains both named and anonymous parameters")
315
316 }
317
318
319
320
321 if variadic {
322 last := params[len(params)-1]
323 last.typ = &Slice{elem: last.typ}
324 check.recordTypeAndValue(list[len(list)-1].Type, typexpr, last.typ, nil)
325 }
326
327 return
328 }
329
View as plain text