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 x.mode = value
228 x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
229 if x.mode == commaerr {
230 x2.typ = universeError
231 }
232 xlist = append(xlist, x2)
233 commaOk = true
234 }
235
236 default:
237
238 xlist = make([]*operand, len(elist))
239 for i, e := range elist {
240 var x operand
241 check.expr(&x, e)
242 xlist[i] = &x
243 }
244 }
245
246 return
247 }
248
249 func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) {
250 rsig = sig
251
252
253 for _, a := range args {
254 switch a.mode {
255 case typexpr:
256 check.errorf(a, 0, "%s used as value", a)
257 return
258 case invalid:
259 return
260 }
261 }
262
263
264
265
266
267
268
269
270
271
272 nargs := len(args)
273 npars := sig.params.Len()
274 ddd := call.Ellipsis.IsValid()
275
276
277 sigParams := sig.params
278 adjusted := false
279 if sig.variadic {
280 if ddd {
281
282 if len(call.Args) == 1 && nargs > 1 {
283
284 check.errorf(inNode(call, call.Ellipsis), _InvalidDotDotDot, "cannot use ... with %d-valued %s", nargs, call.Args[0])
285 return
286 }
287 } else {
288
289 if nargs >= npars-1 {
290
291
292
293 vars := make([]*Var, npars-1)
294 copy(vars, sig.params.vars)
295 last := sig.params.vars[npars-1]
296 typ := last.typ.(*Slice).elem
297 for len(vars) < nargs {
298 vars = append(vars, NewParam(last.pos, last.pkg, last.name, typ))
299 }
300 sigParams = NewTuple(vars...)
301 adjusted = true
302 npars = nargs
303 } else {
304
305 npars--
306 }
307 }
308 } else {
309 if ddd {
310
311 check.errorf(inNode(call, call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun)
312 return
313 }
314
315 }
316
317
318 switch {
319 case nargs < npars:
320 check.errorf(inNode(call, call.Rparen), _WrongArgCount, "not enough arguments in call to %s", call.Fun)
321 return
322 case nargs > npars:
323 check.errorf(args[npars], _WrongArgCount, "too many arguments in call to %s", call.Fun)
324 return
325 }
326
327
328 if len(sig.tparams) > 0 {
329
330
331 targs := check.infer(call, sig.tparams, targs, sigParams, args, true)
332 if targs == nil {
333 return
334 }
335
336
337 rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature)
338 assert(rsig.tparams == nil)
339 check.recordInferred(call, targs, rsig)
340
341
342
343
344 if adjusted {
345 sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.tparams, targs)).(*Tuple)
346 } else {
347 sigParams = rsig.params
348 }
349 }
350
351
352 for i, a := range args {
353 check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun))
354 }
355
356 return
357 }
358
359 var cgoPrefixes = [...]string{
360 "_Ciconst_",
361 "_Cfconst_",
362 "_Csconst_",
363 "_Ctype_",
364 "_Cvar_",
365 "_Cfpvar_fp_",
366 "_Cfunc_",
367 "_Cmacro_",
368 }
369
370 func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
371
372 var (
373 obj Object
374 index []int
375 indirect bool
376 )
377
378 sel := e.Sel.Name
379
380
381
382
383 if ident, ok := e.X.(*ast.Ident); ok {
384 obj := check.lookup(ident.Name)
385 if pname, _ := obj.(*PkgName); pname != nil {
386 assert(pname.pkg == check.pkg)
387 check.recordUse(ident, pname)
388 pname.used = true
389 pkg := pname.imported
390
391 var exp Object
392 funcMode := value
393 if pkg.cgo {
394
395
396
397 if sel == "malloc" {
398 sel = "_CMalloc"
399 } else {
400 funcMode = cgofunc
401 }
402 for _, prefix := range cgoPrefixes {
403
404
405 _, exp = check.scope.LookupParent(prefix+sel, check.pos)
406 if exp != nil {
407 break
408 }
409 }
410 if exp == nil {
411 check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package C", sel)
412 goto Error
413 }
414 check.objDecl(exp, nil)
415 } else {
416 exp = pkg.scope.Lookup(sel)
417 if exp == nil {
418 if !pkg.fake {
419 check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package %s", sel, pkg.name)
420 }
421 goto Error
422 }
423 if !exp.Exported() {
424 check.errorf(e.Sel, _UnexportedName, "%s not exported by package %s", sel, pkg.name)
425
426 }
427 }
428 check.recordUse(e.Sel, exp)
429
430
431
432 switch exp := exp.(type) {
433 case *Const:
434 assert(exp.Val() != nil)
435 x.mode = constant_
436 x.typ = exp.typ
437 x.val = exp.val
438 case *TypeName:
439 x.mode = typexpr
440 x.typ = exp.typ
441 case *Var:
442 x.mode = variable
443 x.typ = exp.typ
444 if pkg.cgo && strings.HasPrefix(exp.name, "_Cvar_") {
445 x.typ = x.typ.(*Pointer).base
446 }
447 case *Func:
448 x.mode = funcMode
449 x.typ = exp.typ
450 if pkg.cgo && strings.HasPrefix(exp.name, "_Cmacro_") {
451 x.mode = value
452 x.typ = x.typ.(*Signature).results.vars[0].typ
453 }
454 case *Builtin:
455 x.mode = builtin
456 x.typ = exp.typ
457 x.id = exp.id
458 default:
459 check.dump("%v: unexpected object %v", e.Sel.Pos(), exp)
460 unreachable()
461 }
462 x.expr = e
463 return
464 }
465 }
466
467 check.exprOrType(x, e.X)
468 if x.mode == invalid {
469 goto Error
470 }
471
472 check.instantiatedOperand(x)
473
474 obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
475 if obj == nil {
476 switch {
477 case index != nil:
478
479 check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)
480 case indirect:
481 check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
482 default:
483 var why string
484 if tpar := asTypeParam(x.typ); tpar != nil {
485
486 switch obj := tpar.Bound().obj.(type) {
487 case nil:
488 why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
489 case *TypeName:
490 why = check.sprintf("interface %s has no method %s", obj.name, sel)
491 }
492 } else {
493 why = check.sprintf("type %s has no field or method %s", x.typ, sel)
494 }
495
496
497 if len(sel) > 0 {
498 var changeCase string
499 if r := rune(sel[0]); unicode.IsUpper(r) {
500 changeCase = string(unicode.ToLower(r)) + sel[1:]
501 } else {
502 changeCase = string(unicode.ToUpper(r)) + sel[1:]
503 }
504 if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
505 why += ", but does have " + changeCase
506 }
507 }
508
509 check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why)
510 }
511 goto Error
512 }
513
514
515 if m, _ := obj.(*Func); m != nil {
516 check.objDecl(m, nil)
517
518
519
520
521 sig := m.typ.(*Signature)
522 if len(sig.rparams) > 0 {
523
524
525
526
527
528 recv := x.typ
529 for i := 0; i < len(index)-1; i++ {
530
531
532 recv = asStruct(derefStructPtr(recv)).Field(index[i]).typ
533 }
534
535
536
537
538
539 if ptrRecv := isPointer(sig.recv.typ); ptrRecv != isPointer(recv) {
540 if ptrRecv {
541 recv = NewPointer(recv)
542 } else {
543 recv = recv.(*Pointer).base
544 }
545 }
546
547
548
549 arg := operand{mode: variable, expr: x.expr, typ: recv}
550 targs := check.infer(m, sig.rparams, nil, NewTuple(sig.recv), []*operand{&arg}, false )
551 if targs == nil {
552
553 goto Error
554 }
555
556
557
558 copy := *m
559 copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.rparams, targs))
560 obj = ©
561 }
562
563
564
565 }
566
567 if x.mode == typexpr {
568
569 m, _ := obj.(*Func)
570 if m == nil {
571
572 check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel)
573 goto Error
574 }
575
576 check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
577
578
579
580 var params []*Var
581 sig := m.typ.(*Signature)
582 if sig.params != nil {
583 params = sig.params.vars
584 }
585 x.mode = value
586 x.typ = &Signature{
587 tparams: sig.tparams,
588 params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "_", x.typ)}, params...)...),
589 results: sig.results,
590 variadic: sig.variadic,
591 }
592
593 check.addDeclDep(m)
594
595 } else {
596
597 switch obj := obj.(type) {
598 case *Var:
599 check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
600 if x.mode == variable || indirect {
601 x.mode = variable
602 } else {
603 x.mode = value
604 }
605 x.typ = obj.typ
606
607 case *Func:
608
609
610 check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
611
612
613
614
615
616
617
618 disabled := true
619 if !disabled && debug {
620
621
622
623
624
625 typ := x.typ
626 if x.mode == variable {
627
628
629
630
631
632 if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) {
633 typ = &Pointer{base: typ}
634 }
635 }
636
637
638
639
640
641
642
643
644 mset := NewMethodSet(typ)
645 if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {
646 check.dump("%v: (%s).%v -> %s", e.Pos(), typ, obj.name, m)
647 check.dump("%s\n", mset)
648
649
650
651
652
653 panic("method sets and lookup don't agree")
654 }
655 }
656
657 x.mode = value
658
659
660 sig := *obj.typ.(*Signature)
661 sig.recv = nil
662 x.typ = &sig
663
664 check.addDeclDep(obj)
665
666 default:
667 unreachable()
668 }
669 }
670
671
672 x.expr = e
673 return
674
675 Error:
676 x.mode = invalid
677 x.expr = e
678 }
679
680
681
682
683
684 func (check *Checker) use(arg ...ast.Expr) {
685 var x operand
686 for _, e := range arg {
687
688
689 if e != nil {
690 check.rawExpr(&x, e, nil)
691 }
692 }
693 }
694
695
696
697
698
699 func (check *Checker) useLHS(arg ...ast.Expr) {
700 var x operand
701 for _, e := range arg {
702
703
704
705 var v *Var
706 var v_used bool
707 if ident, _ := unparen(e).(*ast.Ident); ident != nil {
708
709 if ident.Name == "_" {
710 continue
711 }
712 if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
713
714
715
716 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
717 v = w
718 v_used = v.used
719 }
720 }
721 }
722 check.rawExpr(&x, e, nil)
723 if v != nil {
724 v.used = v_used
725 }
726 }
727 }
728
729
730 func (check *Checker) instantiatedOperand(x *operand) {
731 if x.mode == typexpr && isGeneric(x.typ) {
732 check.errorf(x, _Todo, "cannot use generic type %s without instantiation", x.typ)
733 x.typ = Typ[Invalid]
734 }
735 }
736
View as plain text