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