Source file
src/go/types/call.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "go/ast"
11 "go/internal/typeparams"
12 "go/token"
13 "strings"
14 "unicode"
15 )
16
17
18
19 func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) {
20 xlist := typeparams.UnpackExpr(inst.Index)
21 targs := check.typeList(xlist)
22 if targs == nil {
23 x.mode = invalid
24 x.expr = inst
25 return
26 }
27 assert(len(targs) == len(xlist))
28
29
30 sig := x.typ.(*Signature)
31 got, want := len(targs), len(sig.tparams)
32 if got > want {
33 check.errorf(xlist[got-1], _Todo, "got %d type arguments but want %d", got, want)
34 x.mode = invalid
35 x.expr = inst
36 return
37 }
38
39
40 inferred := false
41
42 if got < want {
43 targs = check.infer(inst, sig.tparams, targs, nil, nil, true)
44 if targs == nil {
45
46 x.mode = invalid
47 x.expr = inst
48 return
49 }
50 got = len(targs)
51 inferred = true
52 }
53 assert(got == want)
54
55
56
57
58 poslist := make([]token.Pos, len(xlist))
59 for i, x := range xlist {
60 poslist[i] = x.Pos()
61 }
62
63
64 res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature)
65 assert(res.tparams == nil)
66 if inferred {
67 check.recordInferred(inst, targs, res)
68 }
69 x.typ = res
70 x.mode = value
71 x.expr = inst
72 }
73
74 func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
75 var inst *ast.IndexExpr
76 if iexpr, _ := call.Fun.(*ast.IndexExpr); iexpr != nil {
77 if check.indexExpr(x, iexpr) {
78
79
80
81 assert(x.mode == value)
82 inst = iexpr
83 }
84 x.expr = iexpr
85 check.record(x)
86 } else {
87 check.exprOrType(x, call.Fun)
88 }
89
90 switch x.mode {
91 case invalid:
92 check.use(call.Args...)
93 x.expr = call
94 return statement
95
96 case typexpr:
97
98 T := x.typ
99 x.mode = invalid
100 switch n := len(call.Args); n {
101 case 0:
102 check.errorf(inNode(call, call.Rparen), _WrongArgCount, "missing argument in conversion to %s", T)
103 case 1:
104 check.expr(x, call.Args[0])
105 if x.mode != invalid {
106 if call.Ellipsis.IsValid() {
107 check.errorf(call.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T)
108 break
109 }
110 if t := asInterface(T); t != nil {
111 check.completeInterface(token.NoPos, t)
112 if t._IsConstraint() {
113 check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T)
114 break
115 }
116 }
117 check.conversion(x, T)
118 }
119 default:
120 check.use(call.Args...)
121 check.errorf(call.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T)
122 }
123 x.expr = call
124 return conversion
125
126 case builtin:
127 id := x.id
128 if !check.builtin(x, call, id) {
129 x.mode = invalid
130 }
131 x.expr = call
132
133 if x.mode != invalid && x.mode != constant_ {
134 check.hasCallOrRecv = true
135 }
136 return predeclaredFuncs[id].kind
137 }
138
139
140 cgocall := x.mode == cgofunc
141
142 sig := asSignature(x.typ)
143 if sig == nil {
144 check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x)
145 x.mode = invalid
146 x.expr = call
147 return statement
148 }
149
150
151 var targs []Type
152 if inst != nil {
153 xlist := typeparams.UnpackExpr(inst.Index)
154 targs = check.typeList(xlist)
155 if targs == nil {
156 check.use(call.Args...)
157 x.mode = invalid
158 x.expr = call
159 return statement
160 }
161 assert(len(targs) == len(xlist))
162
163
164 got, want := len(targs), len(sig.tparams)
165 if got > want {
166 check.errorf(xlist[want], _Todo, "got %d type arguments but want %d", got, want)
167 check.use(call.Args...)
168 x.mode = invalid
169 x.expr = call
170 return statement
171 }
172 }
173
174
175 args, _ := check.exprList(call.Args, false)
176 sig = check.arguments(call, sig, targs, args)
177
178
179 switch sig.results.Len() {
180 case 0:
181 x.mode = novalue
182 case 1:
183 if cgocall {
184 x.mode = commaerr
185 } else {
186 x.mode = value
187 }
188 x.typ = sig.results.vars[0].typ
189 default:
190 x.mode = value
191 x.typ = sig.results
192 }
193 x.expr = call
194 check.hasCallOrRecv = true
195
196
197
198 if x.mode == value && len(sig.tparams) > 0 && isParameterized(sig.tparams, x.typ) {
199 x.mode = invalid
200 }
201
202 return statement
203 }
204
205 func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*operand, commaOk bool) {
206 switch len(elist) {
207 case 0:
208
209
210 case 1:
211
212 e := elist[0]
213 var x operand
214 check.multiExpr(&x, e)
215 if t, ok := x.typ.(*Tuple); ok && x.mode != invalid {
216
217 xlist = make([]*operand, t.Len())
218 for i, v := range t.vars {
219 xlist[i] = &operand{mode: value, expr: e, typ: v.typ}
220 }
221 break
222 }
223
224
225 xlist = []*operand{&x}
226 if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) {
227 x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
228 if x.mode == commaerr {
229 x2.typ = universeError
230 }
231 xlist = append(xlist, x2)
232 commaOk = true
233 }
234
235 default:
236
237 xlist = make([]*operand, len(elist))
238 for i, e := range elist {
239 var x operand
240 check.expr(&x, e)
241 xlist[i] = &x
242 }
243 }
244
245 return
246 }
247
248 func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) {
249 rsig = sig
250
251
252 for _, a := range args {
253 switch a.mode {
254 case typexpr:
255 check.errorf(a, 0, "%s used as value", a)
256 return
257 case invalid:
258 return
259 }
260 }
261
262
263
264
265
266
267
268
269
270
271 nargs := len(args)
272 npars := sig.params.Len()
273 ddd := call.Ellipsis.IsValid()
274
275
276 sigParams := sig.params
277 adjusted := false
278 if sig.variadic {
279 if ddd {
280
281 if len(call.Args) == 1 && nargs > 1 {
282
283 check.errorf(inNode(call, call.Ellipsis), _InvalidDotDotDot, "cannot use ... with %d-valued %s", nargs, call.Args[0])
284 return
285 }
286 } else {
287
288 if nargs >= npars-1 {
289
290
291
292 vars := make([]*Var, npars-1)
293 copy(vars, sig.params.vars)
294 last := sig.params.vars[npars-1]
295 typ := last.typ.(*Slice).elem
296 for len(vars) < nargs {
297 vars = append(vars, NewParam(last.pos, last.pkg, last.name, typ))
298 }
299 sigParams = NewTuple(vars...)
300 adjusted = true
301 npars = nargs
302 } else {
303
304 npars--
305 }
306 }
307 } else {
308 if ddd {
309
310 check.errorf(inNode(call, call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun)
311 return
312 }
313
314 }
315
316
317 switch {
318 case nargs < npars:
319 check.errorf(inNode(call, call.Rparen), _WrongArgCount, "not enough arguments in call to %s", call.Fun)
320 return
321 case nargs > npars:
322 check.errorf(args[npars], _WrongArgCount, "too many arguments in call to %s", call.Fun)
323 return
324 }
325
326
327 if len(sig.tparams) > 0 {
328
329
330 targs := check.infer(call, sig.tparams, targs, sigParams, args, true)
331 if targs == nil {
332 return
333 }
334
335
336 rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature)
337 assert(rsig.tparams == nil)
338 check.recordInferred(call, targs, rsig)
339
340
341
342
343 if adjusted {
344 sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.tparams, targs)).(*Tuple)
345 } else {
346 sigParams = rsig.params
347 }
348 }
349
350
351 for i, a := range args {
352 check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun))
353 }
354
355 return
356 }
357
358 var cgoPrefixes = [...]string{
359 "_Ciconst_",
360 "_Cfconst_",
361 "_Csconst_",
362 "_Ctype_",
363 "_Cvar_",
364 "_Cfpvar_fp_",
365 "_Cfunc_",
366 "_Cmacro_",
367 }
368
369 func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
370
371 var (
372 obj Object
373 index []int
374 indirect bool
375 )
376
377 sel := e.Sel.Name
378
379
380
381
382 if ident, ok := e.X.(*ast.Ident); ok {
383 obj := check.lookup(ident.Name)
384 if pname, _ := obj.(*PkgName); pname != nil {
385 assert(pname.pkg == check.pkg)
386 check.recordUse(ident, pname)
387 pname.used = true
388 pkg := pname.imported
389
390 var exp Object
391 funcMode := value
392 if pkg.cgo {
393
394
395
396 if sel == "malloc" {
397 sel = "_CMalloc"
398 } else {
399 funcMode = cgofunc
400 }
401 for _, prefix := range cgoPrefixes {
402
403
404 _, exp = check.scope.LookupParent(prefix+sel, check.pos)
405 if exp != nil {
406 break
407 }
408 }
409 if exp == nil {
410 check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package C", sel)
411 goto Error
412 }
413 check.objDecl(exp, nil)
414 } else {
415 exp = pkg.scope.Lookup(sel)
416 if exp == nil {
417 if !pkg.fake {
418 check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package %s", sel, pkg.name)
419 }
420 goto Error
421 }
422 if !exp.Exported() {
423 check.errorf(e.Sel, _UnexportedName, "%s not exported by package %s", sel, pkg.name)
424
425 }
426 }
427 check.recordUse(e.Sel, exp)
428
429
430
431 switch exp := exp.(type) {
432 case *Const:
433 assert(exp.Val() != nil)
434 x.mode = constant_
435 x.typ = exp.typ
436 x.val = exp.val
437 case *TypeName:
438 x.mode = typexpr
439 x.typ = exp.typ
440 case *Var:
441 x.mode = variable
442 x.typ = exp.typ
443 if pkg.cgo && strings.HasPrefix(exp.name, "_Cvar_") {
444 x.typ = x.typ.(*Pointer).base
445 }
446 case *Func:
447 x.mode = funcMode
448 x.typ = exp.typ
449 if pkg.cgo && strings.HasPrefix(exp.name, "_Cmacro_") {
450 x.mode = value
451 x.typ = x.typ.(*Signature).results.vars[0].typ
452 }
453 case *Builtin:
454 x.mode = builtin
455 x.typ = exp.typ
456 x.id = exp.id
457 default:
458 check.dump("%v: unexpected object %v", e.Sel.Pos(), exp)
459 unreachable()
460 }
461 x.expr = e
462 return
463 }
464 }
465
466 check.exprOrType(x, e.X)
467 if x.mode == invalid {
468 goto Error
469 }
470
471 check.instantiatedOperand(x)
472
473 obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
474 if obj == nil {
475 switch {
476 case index != nil:
477
478 check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)
479 case indirect:
480 check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
481 default:
482 var why string
483 if tpar := asTypeParam(x.typ); tpar != nil {
484
485 switch obj := tpar.Bound().obj.(type) {
486 case nil:
487 why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
488 case *TypeName:
489 why = check.sprintf("interface %s has no method %s", obj.name, sel)
490 }
491 } else {
492 why = check.sprintf("type %s has no field or method %s", x.typ, sel)
493 }
494
495
496 if len(sel) > 0 {
497 var changeCase string
498 if r := rune(sel[0]); unicode.IsUpper(r) {
499 changeCase = string(unicode.ToLower(r)) + sel[1:]
500 } else {
501 changeCase = string(unicode.ToUpper(r)) + sel[1:]
502 }
503 if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
504 why += ", but does have " + changeCase
505 }
506 }
507
508 check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why)
509 }
510 goto Error
511 }
512
513
514 if m, _ := obj.(*Func); m != nil {
515 check.objDecl(m, nil)
516
517
518
519
520 sig := m.typ.(*Signature)
521 if len(sig.rparams) > 0 {
522
523
524
525
526
527 recv := x.typ
528 for i := 0; i < len(index)-1; i++ {
529
530
531 recv = asStruct(derefStructPtr(recv)).Field(index[i]).typ
532 }
533
534
535
536
537
538 if ptrRecv := isPointer(sig.recv.typ); ptrRecv != isPointer(recv) {
539 if ptrRecv {
540 recv = NewPointer(recv)
541 } else {
542 recv = recv.(*Pointer).base
543 }
544 }
545
546
547
548 arg := operand{mode: variable, expr: x.expr, typ: recv}
549 targs := check.infer(m, sig.rparams, nil, NewTuple(sig.recv), []*operand{&arg}, false )
550 if targs == nil {
551
552 goto Error
553 }
554
555
556
557 copy := *m
558 copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.rparams, targs))
559 obj = ©
560 }
561
562
563
564 }
565
566 if x.mode == typexpr {
567
568 m, _ := obj.(*Func)
569 if m == nil {
570
571 check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel)
572 goto Error
573 }
574
575 check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
576
577
578
579 var params []*Var
580 sig := m.typ.(*Signature)
581 if sig.params != nil {
582 params = sig.params.vars
583 }
584 x.mode = value
585 x.typ = &Signature{
586 tparams: sig.tparams,
587 params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "_", x.typ)}, params...)...),
588 results: sig.results,
589 variadic: sig.variadic,
590 }
591
592 check.addDeclDep(m)
593
594 } else {
595
596 switch obj := obj.(type) {
597 case *Var:
598 check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
599 if x.mode == variable || indirect {
600 x.mode = variable
601 } else {
602 x.mode = value
603 }
604 x.typ = obj.typ
605
606 case *Func:
607
608
609 check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
610
611
612
613
614
615
616
617 disabled := true
618 if !disabled && debug {
619
620
621
622
623
624 typ := x.typ
625 if x.mode == variable {
626
627
628
629
630
631 if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) {
632 typ = &Pointer{base: typ}
633 }
634 }
635
636
637
638
639
640
641
642
643 mset := NewMethodSet(typ)
644 if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {
645 check.dump("%v: (%s).%v -> %s", e.Pos(), typ, obj.name, m)
646 check.dump("%s\n", mset)
647
648
649
650
651
652 panic("method sets and lookup don't agree")
653 }
654 }
655
656 x.mode = value
657
658
659 sig := *obj.typ.(*Signature)
660 sig.recv = nil
661 x.typ = &sig
662
663 check.addDeclDep(obj)
664
665 default:
666 unreachable()
667 }
668 }
669
670
671 x.expr = e
672 return
673
674 Error:
675 x.mode = invalid
676 x.expr = e
677 }
678
679
680
681
682
683 func (check *Checker) use(arg ...ast.Expr) {
684 var x operand
685 for _, e := range arg {
686
687
688 if e != nil {
689 check.rawExpr(&x, e, nil)
690 }
691 }
692 }
693
694
695
696
697
698 func (check *Checker) useLHS(arg ...ast.Expr) {
699 var x operand
700 for _, e := range arg {
701
702
703
704 var v *Var
705 var v_used bool
706 if ident, _ := unparen(e).(*ast.Ident); ident != nil {
707
708 if ident.Name == "_" {
709 continue
710 }
711 if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
712
713
714
715 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
716 v = w
717 v_used = v.used
718 }
719 }
720 }
721 check.rawExpr(&x, e, nil)
722 if v != nil {
723 v.used = v_used
724 }
725 }
726 }
727
728
729 func (check *Checker) instantiatedOperand(x *operand) {
730 if x.mode == typexpr && isGeneric(x.typ) {
731 check.errorf(x, _Todo, "cannot use generic type %s without instantiation", x.typ)
732 x.typ = Typ[Invalid]
733 }
734 }
735
View as plain text