github.com/traefik/yaegi@v0.15.1/interp/typecheck.go (about)

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