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