1package interp
2
3import (
4	"errors"
5	"go/constant"
6	"math"
7	"reflect"
8)
9
10type opPredicates map[action]func(reflect.Type) bool
11
12// typecheck handles all type checking following "go/types" logic.
13//
14// Due to variant type systems (itype vs reflect.Type) a single
15// type system should used, namely reflect.Type with exception
16// of the untyped flag on itype.
17type typecheck struct {
18	scope *scope
19}
20
21// op type checks an expression against a set of expression predicates.
22func (check typecheck) op(p opPredicates, a action, n, c *node, t reflect.Type) error {
23	if pred := p[a]; pred != nil {
24		if !pred(t) {
25			return n.cfgErrorf("invalid operation: operator %v not defined on %s", n.action, c.typ.id())
26		}
27	} else {
28		return n.cfgErrorf("invalid operation: unknown operator %v", n.action)
29	}
30	return nil
31}
32
33// assignment checks if n can be assigned to typ.
34//
35// Use typ == nil to indicate assignment to an untyped blank identifier.
36func (check typecheck) assignment(n *node, typ *itype, context string) error {
37	if n.typ == nil {
38		return n.cfgErrorf("invalid type in %s", context)
39	}
40	if n.typ.untyped {
41		if typ == nil || isInterface(typ) {
42			if typ == nil && n.typ.cat == nilT {
43				return n.cfgErrorf("use of untyped nil in %s", context)
44			}
45			typ = n.typ.defaultType(n.rval, check.scope)
46		}
47		if err := check.convertUntyped(n, typ); err != nil {
48			return err
49		}
50	}
51
52	if typ == nil {
53		return nil
54	}
55
56	if !n.typ.assignableTo(typ) && typ.str != "*unsafe2.dummy" {
57		if context == "" {
58			return n.cfgErrorf("cannot use type %s as type %s", n.typ.id(), typ.id())
59		}
60		return n.cfgErrorf("cannot use type %s as type %s in %s", n.typ.id(), typ.id(), context)
61	}
62	return nil
63}
64
65// assignExpr type checks an assign expression.
66//
67// This is done per pair of assignments.
68func (check typecheck) assignExpr(n, dest, src *node) error {
69	if n.action == aAssign {
70		isConst := n.anc.kind == constDecl
71		if !isConst {
72			// var operations must be typed
73			dest.typ = dest.typ.defaultType(src.rval, check.scope)
74		}
75
76		return check.assignment(src, dest.typ, "assignment")
77	}
78
79	// assignment operations.
80	if n.nleft > 1 || n.nright > 1 {
81		return n.cfgErrorf("assignment operation %s requires single-valued expressions", n.action)
82	}
83
84	return check.binaryExpr(n)
85}
86
87// addressExpr type checks a unary address expression.
88func (check typecheck) addressExpr(n *node) error {
89	c0 := n.child[0]
90	found := false
91	for !found {
92		switch c0.kind {
93		case parenExpr:
94			c0 = c0.child[0]
95			continue
96		case selectorExpr:
97			c0 = c0.child[1]
98			continue
99		case starExpr:
100			c0 = c0.child[0]
101			continue
102		case indexExpr, sliceExpr:
103			c := c0.child[0]
104			if isArray(c.typ) || isMap(c.typ) {
105				c0 = c
106				found = true
107				continue
108			}
109		case compositeLitExpr, identExpr:
110			found = true
111			continue
112		}
113		return n.cfgErrorf("invalid operation: cannot take address of %s [kind: %s]", c0.typ.id(), kinds[c0.kind])
114	}
115	return nil
116}
117
118// starExpr type checks a star expression on a variable.
119func (check typecheck) starExpr(n *node) error {
120	if n.typ.TypeOf().Kind() != reflect.Ptr {
121		return n.cfgErrorf("invalid operation: cannot indirect %q", n.name())
122	}
123	return nil
124}
125
126var unaryOpPredicates = opPredicates{
127	aPos:    isNumber,
128	aNeg:    isNumber,
129	aBitNot: isInt,
130	aNot:    isBoolean,
131}
132
133// unaryExpr type checks a unary expression.
134func (check typecheck) unaryExpr(n *node) error {
135	c0 := n.child[0]
136	t0 := c0.typ.TypeOf()
137
138	if n.action == aRecv {
139		if !isChan(c0.typ) {
140			return n.cfgErrorf("invalid operation: cannot receive from non-channel %s", c0.typ.id())
141		}
142		if isSendChan(c0.typ) {
143			return n.cfgErrorf("invalid operation: cannot receive from send-only channel %s", c0.typ.id())
144		}
145		return nil
146	}
147
148	return check.op(unaryOpPredicates, n.action, n, c0, t0)
149}
150
151// shift type checks a shift binary expression.
152func (check typecheck) shift(n *node) error {
153	c0, c1 := n.child[0], n.child[1]
154	t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf()
155
156	var v0 constant.Value
157	if c0.typ.untyped && c0.rval.IsValid() {
158		v0 = constant.ToInt(c0.rval.Interface().(constant.Value))
159		c0.rval = reflect.ValueOf(v0)
160	}
161
162	if !(c0.typ.untyped && v0 != nil && v0.Kind() == constant.Int || isInt(t0)) {
163		return n.cfgErrorf("invalid operation: shift of type %v", c0.typ.id())
164	}
165
166	switch {
167	case c1.typ.untyped:
168		if err := check.convertUntyped(c1, check.scope.getType("uint")); err != nil {
169			return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id())
170		}
171	case isInt(t1):
172		// nothing to do
173	default:
174		return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id())
175	}
176	return nil
177}
178
179// comparison type checks a comparison binary expression.
180func (check typecheck) comparison(n *node) error {
181	c0, c1 := n.child[0], n.child[1]
182
183	if !c0.typ.assignableTo(c1.typ) && !c1.typ.assignableTo(c0.typ) {
184		return n.cfgErrorf("invalid operation: mismatched types %s and %s", c0.typ.id(), c1.typ.id())
185	}
186
187	ok := false
188	switch n.action {
189	case aEqual, aNotEqual:
190		ok = c0.typ.comparable() && c1.typ.comparable() || c0.typ.isNil() && c1.typ.hasNil() || c1.typ.isNil() && c0.typ.hasNil()
191	case aLower, aLowerEqual, aGreater, aGreaterEqual:
192		ok = c0.typ.ordered() && c1.typ.ordered()
193	}
194	if !ok {
195		typ := c0.typ
196		if typ.isNil() {
197			typ = c1.typ
198		}
199		return n.cfgErrorf("invalid operation: operator %v not defined on %s", n.action, typ.id(), ".")
200	}
201	return nil
202}
203
204var binaryOpPredicates = opPredicates{
205	aAdd: func(typ reflect.Type) bool { return isNumber(typ) || isString(typ) },
206	aSub: isNumber,
207	aMul: isNumber,
208	aQuo: isNumber,
209	aRem: isInt,
210
211	aAnd:    isInt,
212	aOr:     isInt,
213	aXor:    isInt,
214	aAndNot: isInt,
215
216	aLand: isBoolean,
217	aLor:  isBoolean,
218}
219
220// binaryExpr type checks a binary expression.
221func (check typecheck) binaryExpr(n *node) error {
222	c0, c1 := n.child[0], n.child[1]
223
224	a := n.action
225	if isAssignAction(a) {
226		a--
227	}
228
229	if isShiftAction(a) {
230		return check.shift(n)
231	}
232
233	switch n.action {
234	case aAdd:
235		if n.typ == nil {
236			break
237		}
238		// Catch mixing string and number for "+" operator use.
239		k, k0, k1 := isNumber(n.typ.TypeOf()), isNumber(c0.typ.TypeOf()), isNumber(c1.typ.TypeOf())
240		if k != k0 || k != k1 {
241			return n.cfgErrorf("cannot use type %s as type %s in assignment", c0.typ.id(), n.typ.id())
242		}
243	case aRem:
244		if zeroConst(c1) {
245			return n.cfgErrorf("invalid operation: division by zero")
246		}
247	case aQuo:
248		if zeroConst(c1) {
249			return n.cfgErrorf("invalid operation: division by zero")
250		}
251		if c0.rval.IsValid() && c1.rval.IsValid() {
252			// Avoid constant conversions below to ensure correct constant integer quotient.
253			return nil
254		}
255	}
256
257	_ = check.convertUntyped(c0, c1.typ)
258	_ = check.convertUntyped(c1, c0.typ)
259
260	if isComparisonAction(a) {
261		return check.comparison(n)
262	}
263
264	if !c0.typ.equals(c1.typ) {
265		return n.cfgErrorf("invalid operation: mismatched types %s and %s", c0.typ.id(), c1.typ.id())
266	}
267
268	t0 := c0.typ.TypeOf()
269
270	return check.op(binaryOpPredicates, a, n, c0, t0)
271}
272
273func zeroConst(n *node) bool {
274	return n.typ.untyped && constant.Sign(n.rval.Interface().(constant.Value)) == 0
275}
276
277func (check typecheck) index(n *node, max int) error {
278	if err := check.convertUntyped(n, check.scope.getType("int")); err != nil {
279		return err
280	}
281
282	if !isInt(n.typ.TypeOf()) {
283		return n.cfgErrorf("index %s must be integer", n.typ.id())
284	}
285
286	if !n.rval.IsValid() || max < 1 {
287		return nil
288	}
289
290	if int(vInt(n.rval)) >= max {
291		return n.cfgErrorf("index %s is out of bounds", n.typ.id())
292	}
293
294	return nil
295}
296
297// arrayLitExpr type checks an array composite literal expression.
298func (check typecheck) arrayLitExpr(child []*node, typ *itype) error {
299	cat := typ.cat
300	length := typ.length
301	typ = typ.val
302	visited := make(map[int]bool, len(child))
303	index := 0
304	for _, c := range child {
305		n := c
306		switch {
307		case c.kind == keyValueExpr:
308			if err := check.index(c.child[0], length); err != nil {
309				return c.cfgErrorf("index %s must be integer constant", c.child[0].typ.id())
310			}
311			n = c.child[1]
312			index = int(vInt(c.child[0].rval))
313		case cat == arrayT && index >= length:
314			return c.cfgErrorf("index %d is out of bounds (>= %d)", index, length)
315		}
316
317		if visited[index] {
318			return n.cfgErrorf("duplicate index %d in array or slice literal", index)
319		}
320		visited[index] = true
321		index++
322
323		if err := check.assignment(n, typ, "array or slice literal"); err != nil {
324			return err
325		}
326	}
327	return nil
328}
329
330// mapLitExpr type checks an map composite literal expression.
331func (check typecheck) mapLitExpr(child []*node, ktyp, vtyp *itype) error {
332	visited := make(map[interface{}]bool, len(child))
333	for _, c := range child {
334		if c.kind != keyValueExpr {
335			return c.cfgErrorf("missing key in map literal")
336		}
337
338		key, val := c.child[0], c.child[1]
339		if err := check.assignment(key, ktyp, "map literal"); err != nil {
340			return err
341		}
342
343		if key.rval.IsValid() {
344			kval := key.rval.Interface()
345			if visited[kval] {
346				return c.cfgErrorf("duplicate key %s in map literal", kval)
347			}
348			visited[kval] = true
349		}
350
351		if err := check.assignment(val, vtyp, "map literal"); err != nil {
352			return err
353		}
354	}
355	return nil
356}
357
358// structLitExpr type checks a struct composite literal expression.
359func (check typecheck) structLitExpr(child []*node, typ *itype) error {
360	if len(child) == 0 {
361		return nil
362	}
363
364	if child[0].kind == keyValueExpr {
365		// All children must be keyValueExpr
366		visited := make([]bool, len(typ.field))
367		for _, c := range child {
368			if c.kind != keyValueExpr {
369				return c.cfgErrorf("mixture of field:value and value elements in struct literal")
370			}
371
372			key, val := c.child[0], c.child[1]
373			name := key.ident
374			if name == "" {
375				return c.cfgErrorf("invalid field name %s in struct literal", key.typ.id())
376			}
377			i := typ.fieldIndex(name)
378			if i < 0 {
379				return c.cfgErrorf("unknown field %s in struct literal", name)
380			}
381			field := typ.field[i]
382
383			if err := check.assignment(val, field.typ, "struct literal"); err != nil {
384				return err
385			}
386
387			if visited[i] {
388				return c.cfgErrorf("duplicate field name %s in struct literal", name)
389			}
390			visited[i] = true
391		}
392		return nil
393	}
394
395	// No children can be keyValueExpr
396	for i, c := range child {
397		if c.kind == keyValueExpr {
398			return c.cfgErrorf("mixture of field:value and value elements in struct literal")
399		}
400
401		if i >= len(typ.field) {
402			return c.cfgErrorf("too many values in struct literal")
403		}
404		field := typ.field[i]
405		// TODO(nick): check if this field is not exported and in a different package.
406
407		if err := check.assignment(c, field.typ, "struct literal"); err != nil {
408			return err
409		}
410	}
411	if len(child) < len(typ.field) {
412		return child[len(child)-1].cfgErrorf("too few values in struct literal")
413	}
414	return nil
415}
416
417// structBinLitExpr type checks a struct composite literal expression on a binary type.
418func (check typecheck) structBinLitExpr(child []*node, typ reflect.Type) error {
419	if len(child) == 0 {
420		return nil
421	}
422
423	if child[0].kind == keyValueExpr {
424		// All children must be keyValueExpr
425		visited := make(map[string]bool, typ.NumField())
426		for _, c := range child {
427			if c.kind != keyValueExpr {
428				return c.cfgErrorf("mixture of field:value and value elements in struct literal")
429			}
430
431			key, val := c.child[0], c.child[1]
432			name := key.ident
433			if name == "" {
434				return c.cfgErrorf("invalid field name %s in struct literal", key.typ.id())
435			}
436			field, ok := typ.FieldByName(name)
437			if !ok {
438				return c.cfgErrorf("unknown field %s in struct literal", name)
439			}
440
441			if err := check.assignment(val, valueTOf(field.Type), "struct literal"); err != nil {
442				return err
443			}
444
445			if visited[field.Name] {
446				return c.cfgErrorf("duplicate field name %s in struct literal", name)
447			}
448			visited[field.Name] = true
449		}
450		return nil
451	}
452
453	// No children can be keyValueExpr
454	for i, c := range child {
455		if c.kind == keyValueExpr {
456			return c.cfgErrorf("mixture of field:value and value elements in struct literal")
457		}
458
459		if i >= typ.NumField() {
460			return c.cfgErrorf("too many values in struct literal")
461		}
462		field := typ.Field(i)
463		if !canExport(field.Name) {
464			return c.cfgErrorf("implicit assignment to unexported field %s in %s literal", field.Name, typ)
465		}
466
467		if err := check.assignment(c, valueTOf(field.Type), "struct literal"); err != nil {
468			return err
469		}
470	}
471	if len(child) < typ.NumField() {
472		return child[len(child)-1].cfgErrorf("too few values in struct literal")
473	}
474	return nil
475}
476
477// sliceExpr type checks a slice expression.
478func (check typecheck) sliceExpr(n *node) error {
479	c, child := n.child[0], n.child[1:]
480
481	t := c.typ.TypeOf()
482	var low, high, max *node
483	if len(child) >= 1 {
484		if n.action == aSlice {
485			low = child[0]
486		} else {
487			high = child[0]
488		}
489	}
490	if len(child) >= 2 {
491		if n.action == aSlice {
492			high = child[1]
493		} else {
494			max = child[1]
495		}
496	}
497	if len(child) == 3 && n.action == aSlice {
498		max = child[2]
499	}
500
501	l := -1
502	valid := false
503	switch t.Kind() {
504	case reflect.String:
505		valid = true
506		if c.rval.IsValid() {
507			l = len(vString(c.rval))
508		}
509		if max != nil {
510			return max.cfgErrorf("invalid operation: 3-index slice of string")
511		}
512	case reflect.Array:
513		valid = true
514		l = t.Len()
515		// TODO(marc): check addressable status of array object (i.e. composite arrays are not).
516	case reflect.Slice:
517		valid = true
518	case reflect.Ptr:
519		if t.Elem().Kind() == reflect.Array {
520			valid = true
521			l = t.Elem().Len()
522		}
523	}
524	if !valid {
525		return c.cfgErrorf("cannot slice type %s", c.typ.id())
526	}
527
528	var ind [3]int64
529	for i, nod := range []*node{low, high, max} {
530		x := int64(-1)
531		switch {
532		case nod != nil:
533			max := -1
534			if l >= 0 {
535				max = l + 1
536			}
537			if err := check.index(nod, max); err != nil {
538				return err
539			}
540			if nod.rval.IsValid() {
541				x = vInt(nod.rval)
542			}
543		case i == 0:
544			x = 0
545		case l >= 0:
546			x = int64(l)
547		}
548		ind[i] = x
549	}
550
551	for i, x := range ind[:len(ind)-1] {
552		if x <= 0 {
553			continue
554		}
555		for _, y := range ind[i+1:] {
556			if y < 0 || x <= y {
557				continue
558			}
559			return n.cfgErrorf("invalid index values, must be low <= high <= max")
560		}
561	}
562	return nil
563}
564
565// typeAssertionExpr type checks a type assert expression.
566func (check typecheck) typeAssertionExpr(n *node, typ *itype) error {
567	// TODO(nick): This type check is not complete and should be revisited once
568	// https://github.com/golang/go/issues/39717 lands. It is currently impractical to
569	// type check Named types as they cannot be asserted.
570
571	if n.typ.TypeOf().Kind() != reflect.Interface {
572		return n.cfgErrorf("invalid type assertion: non-interface type %s on left", n.typ.id())
573	}
574	ims := n.typ.methods()
575	if len(ims) == 0 {
576		// Empty interface must be a dynamic check.
577		return nil
578	}
579
580	if isInterface(typ) {
581		// Asserting to an interface is a dynamic check as we must look to the
582		// underlying struct.
583		return nil
584	}
585
586	for name := range ims {
587		im := lookupFieldOrMethod(n.typ, name)
588		tm := lookupFieldOrMethod(typ, name)
589		if im == nil {
590			// This should not be possible.
591			continue
592		}
593		if tm == nil {
594			return n.cfgErrorf("impossible type assertion: %s does not implement %s (missing %v method)", typ.id(), n.typ.id(), name)
595		}
596		if tm.recv != nil && tm.recv.TypeOf().Kind() == reflect.Ptr && typ.TypeOf().Kind() != reflect.Ptr {
597			return n.cfgErrorf("impossible type assertion: %s does not implement %s as %q method has a pointer receiver", typ.id(), n.typ.id(), name)
598		}
599
600		err := n.cfgErrorf("impossible type assertion: %s does not implement %s", typ.id(), n.typ.id())
601		if im.numIn() != tm.numIn() || im.numOut() != tm.numOut() {
602			return err
603		}
604		for i := 0; i < im.numIn(); i++ {
605			if !im.in(i).equals(tm.in(i)) {
606				return err
607			}
608		}
609		for i := 0; i < im.numOut(); i++ {
610			if !im.out(i).equals(tm.out(i)) {
611				return err
612			}
613		}
614	}
615	return nil
616}
617
618// conversion type checks the conversion of n to typ.
619func (check typecheck) conversion(n *node, typ *itype) error {
620	var c constant.Value
621	if n.rval.IsValid() {
622		if con, ok := n.rval.Interface().(constant.Value); ok {
623			c = con
624		}
625	}
626
627	var ok bool
628	switch {
629	case c != nil && isConstType(typ):
630		switch t := typ.TypeOf(); {
631		case representableConst(c, t):
632			ok = true
633		case isInt(n.typ.TypeOf()) && isString(t):
634			codepoint := int64(-1)
635			if i, ok := constant.Int64Val(c); ok {
636				codepoint = i
637			}
638			n.rval = reflect.ValueOf(constant.MakeString(string(rune(codepoint))))
639			ok = true
640		}
641
642	case n.typ.convertibleTo(typ):
643		ok = true
644	}
645	if !ok {
646		return n.cfgErrorf("cannot convert expression of type %s to type %s", n.typ.id(), typ.id())
647	}
648	if !n.typ.untyped || c == nil {
649		return nil
650	}
651	if isInterface(typ) || !isConstType(typ) {
652		typ = n.typ.defaultType(n.rval, check.scope)
653	}
654	return check.convertUntyped(n, typ)
655}
656
657type param struct {
658	nod *node
659	typ *itype
660}
661
662func (p param) Type() *itype {
663	if p.typ != nil {
664		return p.typ
665	}
666	return p.nod.typ
667}
668
669// unpackParams unpacks child parameters into a slice of param.
670// If there is only 1 child and it is a callExpr with an n-value return,
671// the return types are returned, otherwise the original child nodes are
672// returned with nil typ.
673func (check typecheck) unpackParams(child []*node) (params []param) {
674	if len(child) == 1 && isCall(child[0]) && child[0].child[0].typ.numOut() > 1 {
675		c0 := child[0]
676		ftyp := child[0].child[0].typ
677		for i := 0; i < ftyp.numOut(); i++ {
678			params = append(params, param{nod: c0, typ: ftyp.out(i)})
679		}
680		return params
681	}
682
683	for _, c := range child {
684		params = append(params, param{nod: c})
685	}
686	return params
687}
688
689var builtinFuncs = map[string]struct {
690	args     int
691	variadic bool
692}{
693	bltnAppend:  {args: 1, variadic: true},
694	bltnCap:     {args: 1, variadic: false},
695	bltnClose:   {args: 1, variadic: false},
696	bltnComplex: {args: 2, variadic: false},
697	bltnImag:    {args: 1, variadic: false},
698	bltnCopy:    {args: 2, variadic: false},
699	bltnDelete:  {args: 2, variadic: false},
700	bltnLen:     {args: 1, variadic: false},
701	bltnMake:    {args: 1, variadic: true},
702	bltnNew:     {args: 1, variadic: false},
703	bltnPanic:   {args: 1, variadic: false},
704	bltnPrint:   {args: 0, variadic: true},
705	bltnPrintln: {args: 0, variadic: true},
706	bltnReal:    {args: 1, variadic: false},
707	bltnRecover: {args: 0, variadic: false},
708}
709
710func (check typecheck) builtin(name string, n *node, child []*node, ellipsis bool) error {
711	fun := builtinFuncs[name]
712	if ellipsis && name != bltnAppend {
713		return n.cfgErrorf("invalid use of ... with builtin %s", name)
714	}
715
716	var params []param
717	nparams := len(child)
718	switch name {
719	case bltnMake, bltnNew:
720		// Special param handling
721	default:
722		params = check.unpackParams(child)
723		nparams = len(params)
724	}
725
726	if nparams < fun.args {
727		return n.cfgErrorf("not enough arguments in call to %s", name)
728	} else if !fun.variadic && nparams > fun.args {
729		return n.cfgErrorf("too many arguments for %s", name)
730	}
731
732	switch name {
733	case bltnAppend:
734		typ := params[0].Type()
735		t := typ.TypeOf()
736		if t == nil || t.Kind() != reflect.Slice {
737			return params[0].nod.cfgErrorf("first argument to append must be slice; have %s", typ.id())
738		}
739
740		if nparams == 1 {
741			return nil
742		}
743		// Special case append([]byte, "test"...) is allowed.
744		t1 := params[1].Type()
745		if nparams == 2 && ellipsis && t.Elem().Kind() == reflect.Uint8 && t1.TypeOf().Kind() == reflect.String {
746			if t1.untyped {
747				return check.convertUntyped(params[1].nod, check.scope.getType("string"))
748			}
749			return nil
750		}
751
752		fun := &node{
753			typ: &itype{
754				cat: funcT,
755				arg: []*itype{
756					typ,
757					{cat: variadicT, val: valueTOf(t.Elem())},
758				},
759				ret: []*itype{typ},
760			},
761			ident: "append",
762		}
763		return check.arguments(n, child, fun, ellipsis)
764	case bltnCap, bltnLen:
765		typ := arrayDeref(params[0].Type())
766		ok := false
767		switch typ.TypeOf().Kind() {
768		case reflect.Array, reflect.Slice, reflect.Chan:
769			ok = true
770		case reflect.String, reflect.Map:
771			ok = name == bltnLen
772		}
773		if !ok {
774			return params[0].nod.cfgErrorf("invalid argument for %s", name)
775		}
776	case bltnClose:
777		p := params[0]
778		typ := p.Type()
779		t := typ.TypeOf()
780		if t.Kind() != reflect.Chan {
781			return p.nod.cfgErrorf("invalid operation: non-chan type %s", p.nod.typ.id())
782		}
783		if t.ChanDir() == reflect.RecvDir {
784			return p.nod.cfgErrorf("invalid operation: cannot close receive-only channel")
785		}
786	case bltnComplex:
787		var err error
788		p0, p1 := params[0], params[1]
789		typ0, typ1 := p0.Type(), p1.Type()
790		switch {
791		case typ0.untyped && !typ1.untyped:
792			err = check.convertUntyped(p0.nod, typ1)
793		case !typ0.untyped && typ1.untyped:
794			err = check.convertUntyped(p1.nod, typ0)
795		case typ0.untyped && typ1.untyped:
796			fltType := check.scope.getType("float64")
797			err = check.convertUntyped(p0.nod, fltType)
798			if err != nil {
799				break
800			}
801			err = check.convertUntyped(p1.nod, fltType)
802		}
803		if err != nil {
804			return err
805		}
806
807		// check we have the correct types after conversion.
808		typ0, typ1 = p0.Type(), p1.Type()
809		if !typ0.equals(typ1) {
810			return n.cfgErrorf("invalid operation: mismatched types %s and %s", typ0.id(), typ1.id())
811		}
812		if !isFloat(typ0.TypeOf()) {
813			return n.cfgErrorf("invalid operation: arguments have type %s, expected floating-point", typ0.id())
814		}
815	case bltnImag, bltnReal:
816		p := params[0]
817		typ := p.Type()
818		if typ.untyped {
819			if err := check.convertUntyped(p.nod, check.scope.getType("complex128")); err != nil {
820				return err
821			}
822		}
823		typ = p.Type()
824		if !isComplex(typ.TypeOf()) {
825			return p.nod.cfgErrorf("invalid argument type %s for %s", typ.id(), name)
826		}
827	case bltnCopy:
828		typ0, typ1 := params[0].Type(), params[1].Type()
829		var t0, t1 reflect.Type
830		if t := typ0.TypeOf(); t.Kind() == reflect.Slice {
831			t0 = t.Elem()
832		}
833
834		switch t := typ1.TypeOf(); t.Kind() {
835		case reflect.String:
836			t1 = reflect.TypeOf(byte(1))
837		case reflect.Slice:
838			t1 = t.Elem()
839		}
840
841		if t0 == nil || t1 == nil {
842			return n.cfgErrorf("copy expects slice arguments")
843		}
844		if !reflect.DeepEqual(t0, t1) {
845			return n.cfgErrorf("arguments to copy have different element types %s and %s", typ0.id(), typ1.id())
846		}
847	case bltnDelete:
848		typ := params[0].Type()
849		if typ.TypeOf().Kind() != reflect.Map {
850			return params[0].nod.cfgErrorf("first argument to delete must be map; have %s", typ.id())
851		}
852		ktyp := params[1].Type()
853		if typ.key != nil && !ktyp.assignableTo(typ.key) {
854			return params[1].nod.cfgErrorf("cannot use %s as type %s in delete", ktyp.id(), typ.key.id())
855		}
856	case bltnMake:
857		var min int
858		switch child[0].typ.TypeOf().Kind() {
859		case reflect.Slice:
860			min = 2
861		case reflect.Map, reflect.Chan:
862			min = 1
863		default:
864			return child[0].cfgErrorf("cannot make %s; type must be slice, map, or channel", child[0].typ.id())
865		}
866		if nparams < min {
867			return n.cfgErrorf("not enough arguments in call to make")
868		} else if nparams > min+1 {
869			return n.cfgErrorf("too many arguments for make")
870		}
871
872		var sizes []int
873		for _, c := range child[1:] {
874			if err := check.index(c, -1); err != nil {
875				return err
876			}
877			if c.rval.IsValid() {
878				sizes = append(sizes, int(vInt(c.rval)))
879			}
880		}
881		for len(sizes) == 2 && sizes[0] > sizes[1] {
882			return n.cfgErrorf("len larger than cap in make")
883		}
884
885	case bltnPanic:
886		return check.assignment(params[0].nod, check.scope.getType("interface{}"), "argument to panic")
887	case bltnPrint, bltnPrintln:
888		for _, param := range params {
889			if param.typ != nil {
890				continue
891			}
892
893			if err := check.assignment(param.nod, nil, "argument to "+name); err != nil {
894				return err
895			}
896		}
897	case bltnRecover, bltnNew:
898		// Nothing to do.
899	default:
900		return n.cfgErrorf("unsupported builtin %s", name)
901	}
902	return nil
903}
904
905// arrayDeref returns A if typ is *A, otherwise typ.
906func arrayDeref(typ *itype) *itype {
907	if typ.cat == valueT && typ.TypeOf().Kind() == reflect.Ptr {
908		t := typ.TypeOf()
909		if t.Elem().Kind() == reflect.Array {
910			return valueTOf(t.Elem())
911		}
912		return typ
913	}
914
915	if typ.cat == ptrT && typ.val.cat == arrayT {
916		return typ.val
917	}
918	return typ
919}
920
921// arguments type checks the call expression arguments.
922func (check typecheck) arguments(n *node, child []*node, fun *node, ellipsis bool) error {
923	params := check.unpackParams(child)
924	l := len(child)
925	if ellipsis {
926		if !fun.typ.isVariadic() {
927			return n.cfgErrorf("invalid use of ..., corresponding parameter is non-variadic")
928		}
929		if len(params) > l {
930			return child[0].cfgErrorf("cannot use ... with %d-valued %s", child[0].child[0].typ.numOut(), child[0].child[0].typ.id())
931		}
932	}
933
934	var cnt int
935	for i, param := range params {
936		ellip := i == l-1 && ellipsis
937		if err := check.argument(param, fun.typ, cnt, l, ellip); err != nil {
938			return err
939		}
940		cnt++
941	}
942
943	if fun.typ.isVariadic() {
944		cnt++
945	}
946	if cnt < fun.typ.numIn() {
947		return n.cfgErrorf("not enough arguments in call to %s", fun.name())
948	}
949	return nil
950}
951
952func (check typecheck) argument(p param, ftyp *itype, i, l int, ellipsis bool) error {
953	atyp := getArg(ftyp, i)
954	if atyp == nil {
955		return p.nod.cfgErrorf("too many arguments")
956	}
957
958	if p.typ == nil && isCall(p.nod) && p.nod.child[0].typ.numOut() != 1 {
959		if l == 1 {
960			return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp))
961		}
962		return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), atyp.id())
963	}
964
965	if ellipsis {
966		if i != ftyp.numIn()-1 {
967			return p.nod.cfgErrorf("can only use ... with matching parameter")
968		}
969		t := p.Type().TypeOf()
970		if t.Kind() != reflect.Slice || !(valueTOf(t.Elem())).assignableTo(atyp) {
971			return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.typ.id(), (sliceOf(atyp)).id())
972		}
973		return nil
974	}
975
976	if p.typ != nil {
977		if !p.typ.assignableTo(atyp) {
978			return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp))
979		}
980		return nil
981	}
982	return check.assignment(p.nod, atyp, "")
983}
984
985func getArg(ftyp *itype, i int) *itype {
986	l := ftyp.numIn()
987	switch {
988	case ftyp.isVariadic() && i >= l-1:
989		arg := ftyp.in(l - 1).val
990		return arg
991	case i < l:
992		return ftyp.in(i)
993	case ftyp.cat == valueT && i < ftyp.rtype.NumIn():
994		return valueTOf(ftyp.rtype.In(i))
995	default:
996		return nil
997	}
998}
999
1000func getArgsID(ftyp *itype) string {
1001	res := "("
1002	for i, arg := range ftyp.arg {
1003		if i > 0 {
1004			res += ","
1005		}
1006		res += arg.id()
1007	}
1008	res += ")"
1009	return res
1010}
1011
1012var errCantConvert = errors.New("cannot convert")
1013
1014func (check typecheck) convertUntyped(n *node, typ *itype) error {
1015	if n.typ == nil || !n.typ.untyped || typ == nil {
1016		return nil
1017	}
1018
1019	convErr := n.cfgErrorf("cannot convert %s to %s", n.typ.id(), typ.id())
1020
1021	ntyp, ttyp := n.typ.TypeOf(), typ.TypeOf()
1022	if typ.untyped {
1023		// Both n and target are untyped.
1024		nkind, tkind := ntyp.Kind(), ttyp.Kind()
1025		if isNumber(ntyp) && isNumber(ttyp) {
1026			if nkind < tkind {
1027				n.typ = typ
1028			}
1029		} else if nkind != tkind {
1030			return convErr
1031		}
1032		return nil
1033	}
1034
1035	var (
1036		ityp *itype
1037		rtyp reflect.Type
1038		err  error
1039	)
1040	switch {
1041	case typ.isNil() && n.typ.isNil():
1042		n.typ = typ
1043		return nil
1044	case isNumber(ttyp) || isString(ttyp) || isBoolean(ttyp):
1045		ityp = typ
1046		rtyp = ttyp
1047	case isInterface(typ):
1048		if n.typ.isNil() {
1049			return nil
1050		}
1051		if len(n.typ.methods()) > 0 { // untyped cannot be set to iface
1052			return convErr
1053		}
1054		ityp = n.typ.defaultType(n.rval, check.scope)
1055		rtyp = ntyp
1056	case isArray(typ) || isMap(typ) || isChan(typ) || isFunc(typ) || isPtr(typ):
1057		// TODO(nick): above we are acting on itype, but really it is an rtype check. This is not clear which type
1058		// 		 	   plain we are in. Fix this later.
1059		if !n.typ.isNil() {
1060			return convErr
1061		}
1062		return nil
1063	default:
1064		return convErr
1065	}
1066
1067	if err := check.representable(n, rtyp); err != nil {
1068		return err
1069	}
1070	n.rval, err = check.convertConst(n.rval, rtyp)
1071	if err != nil {
1072		if errors.Is(err, errCantConvert) {
1073			return convErr
1074		}
1075		return n.cfgErrorf(err.Error())
1076	}
1077	n.typ = ityp
1078	return nil
1079}
1080
1081func (check typecheck) representable(n *node, t reflect.Type) error {
1082	if !n.rval.IsValid() {
1083		// TODO(nick): This should be an error as the const is in the frame which is undesirable.
1084		return nil
1085	}
1086	c, ok := n.rval.Interface().(constant.Value)
1087	if !ok {
1088		// TODO(nick): This should be an error as untyped strings and bools should be constant.Values.
1089		return nil
1090	}
1091
1092	if !representableConst(c, t) {
1093		typ := n.typ.TypeOf()
1094		if isNumber(typ) && isNumber(t) {
1095			// numeric conversion : error msg
1096			//
1097			// integer -> integer : overflows
1098			// integer -> float   : overflows (actually not possible)
1099			// float   -> integer : truncated
1100			// float   -> float   : overflows
1101			//
1102			if !isInt(typ) && isInt(t) {
1103				return n.cfgErrorf("%s truncated to %s", c.ExactString(), t.Kind().String())
1104			}
1105			return n.cfgErrorf("%s overflows %s", c.ExactString(), t.Kind().String())
1106		}
1107		return n.cfgErrorf("cannot convert %s to %s", c.ExactString(), t.Kind().String())
1108	}
1109	return nil
1110}
1111
1112func (check typecheck) convertConst(v reflect.Value, t reflect.Type) (reflect.Value, error) {
1113	if !v.IsValid() {
1114		// TODO(nick): This should be an error as the const is in the frame which is undesirable.
1115		return v, nil
1116	}
1117	c, ok := v.Interface().(constant.Value)
1118	if !ok {
1119		// TODO(nick): This should be an error as untyped strings and bools should be constant.Values.
1120		return v, nil
1121	}
1122
1123	kind := t.Kind()
1124	switch kind {
1125	case reflect.Bool:
1126		v = reflect.ValueOf(constant.BoolVal(c))
1127	case reflect.String:
1128		v = reflect.ValueOf(constant.StringVal(c))
1129	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1130		i, _ := constant.Int64Val(constant.ToInt(c))
1131		v = reflect.ValueOf(i).Convert(t)
1132	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1133		i, _ := constant.Uint64Val(constant.ToInt(c))
1134		v = reflect.ValueOf(i).Convert(t)
1135	case reflect.Float32:
1136		f, _ := constant.Float32Val(constant.ToFloat(c))
1137		v = reflect.ValueOf(f)
1138	case reflect.Float64:
1139		f, _ := constant.Float64Val(constant.ToFloat(c))
1140		v = reflect.ValueOf(f)
1141	case reflect.Complex64:
1142		r, _ := constant.Float32Val(constant.Real(c))
1143		i, _ := constant.Float32Val(constant.Imag(c))
1144		v = reflect.ValueOf(complex(r, i)).Convert(t)
1145	case reflect.Complex128:
1146		r, _ := constant.Float64Val(constant.Real(c))
1147		i, _ := constant.Float64Val(constant.Imag(c))
1148		v = reflect.ValueOf(complex(r, i)).Convert(t)
1149	default:
1150		return v, errCantConvert
1151	}
1152	return v, nil
1153}
1154
1155var bitlen = [...]int{
1156	reflect.Int:     64,
1157	reflect.Int8:    8,
1158	reflect.Int16:   16,
1159	reflect.Int32:   32,
1160	reflect.Int64:   64,
1161	reflect.Uint:    64,
1162	reflect.Uint8:   8,
1163	reflect.Uint16:  16,
1164	reflect.Uint32:  32,
1165	reflect.Uint64:  64,
1166	reflect.Uintptr: 64,
1167}
1168
1169func representableConst(c constant.Value, t reflect.Type) bool {
1170	switch {
1171	case isInt(t):
1172		x := constant.ToInt(c)
1173		if x.Kind() != constant.Int {
1174			return false
1175		}
1176		switch t.Kind() {
1177		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
1178			if _, ok := constant.Int64Val(x); !ok {
1179				return false
1180			}
1181		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
1182			if _, ok := constant.Uint64Val(x); !ok {
1183				return false
1184			}
1185		default:
1186			return false
1187		}
1188		return constant.BitLen(x) <= bitlen[t.Kind()]
1189	case isFloat(t):
1190		x := constant.ToFloat(c)
1191		if x.Kind() != constant.Float {
1192			return false
1193		}
1194		switch t.Kind() {
1195		case reflect.Float32:
1196			f, _ := constant.Float32Val(x)
1197			return !math.IsInf(float64(f), 0)
1198		case reflect.Float64:
1199			f, _ := constant.Float64Val(x)
1200			return !math.IsInf(f, 0)
1201		default:
1202			return false
1203		}
1204	case isComplex(t):
1205		x := constant.ToComplex(c)
1206		if x.Kind() != constant.Complex {
1207			return false
1208		}
1209		switch t.Kind() {
1210		case reflect.Complex64:
1211			r, _ := constant.Float32Val(constant.Real(x))
1212			i, _ := constant.Float32Val(constant.Imag(x))
1213			return !math.IsInf(float64(r), 0) && !math.IsInf(float64(i), 0)
1214		case reflect.Complex128:
1215			r, _ := constant.Float64Val(constant.Real(x))
1216			i, _ := constant.Float64Val(constant.Imag(x))
1217			return !math.IsInf(r, 0) && !math.IsInf(i, 0)
1218		default:
1219			return false
1220		}
1221	case isString(t):
1222		return c.Kind() == constant.String
1223	case isBoolean(t):
1224		return c.Kind() == constant.Bool
1225	default:
1226		return false
1227	}
1228}
1229
1230func isShiftAction(a action) bool {
1231	switch a {
1232	case aShl, aShr, aShlAssign, aShrAssign:
1233		return true
1234	}
1235	return false
1236}
1237
1238func isComparisonAction(a action) bool {
1239	switch a {
1240	case aEqual, aNotEqual, aGreater, aGreaterEqual, aLower, aLowerEqual:
1241		return true
1242	}
1243	return false
1244}
1245