gitlab.com/ethan.reesor/vscode-notebooks/yaegi@v0.0.0-20220417214422-5c573557938e/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  	aPos:    isNumber,
   129  	aNeg:    isNumber,
   130  	aBitNot: isInt,
   131  	aNot:    isBoolean,
   132  }
   133  
   134  // unaryExpr type checks a unary expression.
   135  func (check typecheck) unaryExpr(n *node) error {
   136  	c0 := n.child[0]
   137  	t0 := c0.typ.TypeOf()
   138  
   139  	if n.action == aRecv {
   140  		if !isChan(c0.typ) {
   141  			return n.cfgErrorf("invalid operation: cannot receive from non-channel %s", c0.typ.id())
   142  		}
   143  		if isSendChan(c0.typ) {
   144  			return n.cfgErrorf("invalid operation: cannot receive from send-only channel %s", c0.typ.id())
   145  		}
   146  		return nil
   147  	}
   148  
   149  	return check.op(unaryOpPredicates, n.action, n, c0, t0)
   150  }
   151  
   152  // shift type checks a shift binary expression.
   153  func (check typecheck) shift(n *node) error {
   154  	c0, c1 := n.child[0], n.child[1]
   155  	t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf()
   156  
   157  	var v0 constant.Value
   158  	if c0.typ.untyped && c0.rval.IsValid() {
   159  		v0 = constant.ToInt(c0.rval.Interface().(constant.Value))
   160  		c0.rval = reflect.ValueOf(v0)
   161  	}
   162  
   163  	if !(c0.typ.untyped && v0 != nil && v0.Kind() == constant.Int || isInt(t0)) {
   164  		return n.cfgErrorf("invalid operation: shift of type %v", c0.typ.id())
   165  	}
   166  
   167  	switch {
   168  	case c1.typ.untyped:
   169  		if err := check.convertUntyped(c1, check.scope.getType("uint")); err != nil {
   170  			return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id())
   171  		}
   172  	case isInt(t1):
   173  		// nothing to do
   174  	default:
   175  		return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id())
   176  	}
   177  	return nil
   178  }
   179  
   180  // comparison type checks a comparison binary expression.
   181  func (check typecheck) comparison(n *node) error {
   182  	c0, c1 := n.child[0], n.child[1]
   183  
   184  	if !c0.typ.assignableTo(c1.typ) && !c1.typ.assignableTo(c0.typ) {
   185  		return n.cfgErrorf("invalid operation: mismatched types %s and %s", c0.typ.id(), c1.typ.id())
   186  	}
   187  
   188  	ok := false
   189  	switch n.action {
   190  	case aEqual, aNotEqual:
   191  		ok = c0.typ.comparable() && c1.typ.comparable() || c0.typ.isNil() && c1.typ.hasNil() || c1.typ.isNil() && c0.typ.hasNil()
   192  	case aLower, aLowerEqual, aGreater, aGreaterEqual:
   193  		ok = c0.typ.ordered() && c1.typ.ordered()
   194  	}
   195  	if !ok {
   196  		typ := c0.typ
   197  		if typ.isNil() {
   198  			typ = c1.typ
   199  		}
   200  		return n.cfgErrorf("invalid operation: operator %v not defined on %s", n.action, typ.id(), ".")
   201  	}
   202  	return nil
   203  }
   204  
   205  var binaryOpPredicates = opPredicates{
   206  	aAdd: func(typ reflect.Type) bool { return isNumber(typ) || isString(typ) },
   207  	aSub: isNumber,
   208  	aMul: isNumber,
   209  	aQuo: isNumber,
   210  	aRem: isInt,
   211  
   212  	aAnd:    isInt,
   213  	aOr:     isInt,
   214  	aXor:    isInt,
   215  	aAndNot: isInt,
   216  
   217  	aLand: isBoolean,
   218  	aLor:  isBoolean,
   219  }
   220  
   221  // binaryExpr type checks a binary expression.
   222  func (check typecheck) binaryExpr(n *node) error {
   223  	c0, c1 := n.child[0], n.child[1]
   224  
   225  	a := n.action
   226  	if isAssignAction(a) {
   227  		a--
   228  	}
   229  
   230  	if isShiftAction(a) {
   231  		return check.shift(n)
   232  	}
   233  
   234  	switch n.action {
   235  	case aAdd:
   236  		if n.typ == nil {
   237  			break
   238  		}
   239  		// Catch mixing string and number for "+" operator use.
   240  		k, k0, k1 := isNumber(n.typ.TypeOf()), isNumber(c0.typ.TypeOf()), isNumber(c1.typ.TypeOf())
   241  		if k != k0 || k != k1 {
   242  			return n.cfgErrorf("cannot use type %s as type %s in assignment", c0.typ.id(), n.typ.id())
   243  		}
   244  	case aRem:
   245  		if zeroConst(c1) {
   246  			return n.cfgErrorf("invalid operation: division by zero")
   247  		}
   248  	case aQuo:
   249  		if zeroConst(c1) {
   250  			return n.cfgErrorf("invalid operation: division by zero")
   251  		}
   252  		if c0.rval.IsValid() && c1.rval.IsValid() {
   253  			// Avoid constant conversions below to ensure correct constant integer quotient.
   254  			return nil
   255  		}
   256  	}
   257  
   258  	_ = check.convertUntyped(c0, c1.typ)
   259  	_ = check.convertUntyped(c1, c0.typ)
   260  
   261  	if isComparisonAction(a) {
   262  		return check.comparison(n)
   263  	}
   264  
   265  	if !c0.typ.equals(c1.typ) {
   266  		return n.cfgErrorf("invalid operation: mismatched types %s and %s", c0.typ.id(), c1.typ.id())
   267  	}
   268  
   269  	t0 := c0.typ.TypeOf()
   270  
   271  	return check.op(binaryOpPredicates, a, n, c0, t0)
   272  }
   273  
   274  func zeroConst(n *node) bool {
   275  	return n.typ.untyped && constant.Sign(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  	c, child := n.child[0], n.child[1:]
   481  
   482  	t := c.typ.TypeOf()
   483  	var low, high, max *node
   484  	if len(child) >= 1 {
   485  		if n.action == aSlice {
   486  			low = child[0]
   487  		} else {
   488  			high = child[0]
   489  		}
   490  	}
   491  	if len(child) >= 2 {
   492  		if n.action == aSlice {
   493  			high = child[1]
   494  		} else {
   495  			max = child[1]
   496  		}
   497  	}
   498  	if len(child) == 3 && n.action == aSlice {
   499  		max = child[2]
   500  	}
   501  
   502  	l := -1
   503  	valid := false
   504  	switch t.Kind() {
   505  	case reflect.String:
   506  		valid = true
   507  		if c.rval.IsValid() {
   508  			l = len(vString(c.rval))
   509  		}
   510  		if max != nil {
   511  			return max.cfgErrorf("invalid operation: 3-index slice of string")
   512  		}
   513  	case reflect.Array:
   514  		valid = true
   515  		l = t.Len()
   516  		// TODO(marc): check addressable status of array object (i.e. composite arrays are not).
   517  	case reflect.Slice:
   518  		valid = true
   519  	case reflect.Ptr:
   520  		if t.Elem().Kind() == reflect.Array {
   521  			valid = true
   522  			l = t.Elem().Len()
   523  		}
   524  	}
   525  	if !valid {
   526  		return c.cfgErrorf("cannot slice type %s", c.typ.id())
   527  	}
   528  
   529  	var ind [3]int64
   530  	for i, nod := range []*node{low, high, max} {
   531  		x := int64(-1)
   532  		switch {
   533  		case nod != nil:
   534  			max := -1
   535  			if l >= 0 {
   536  				max = l + 1
   537  			}
   538  			if err := check.index(nod, max); err != nil {
   539  				return err
   540  			}
   541  			if nod.rval.IsValid() {
   542  				x = vInt(nod.rval)
   543  			}
   544  		case i == 0:
   545  			x = 0
   546  		case l >= 0:
   547  			x = int64(l)
   548  		}
   549  		ind[i] = x
   550  	}
   551  
   552  	for i, x := range ind[:len(ind)-1] {
   553  		if x <= 0 {
   554  			continue
   555  		}
   556  		for _, y := range ind[i+1:] {
   557  			if y < 0 || x <= y {
   558  				continue
   559  			}
   560  			return n.cfgErrorf("invalid index values, must be low <= high <= max")
   561  		}
   562  	}
   563  	return nil
   564  }
   565  
   566  // typeAssertionExpr type checks a type assert expression.
   567  func (check typecheck) typeAssertionExpr(n *node, typ *itype) error {
   568  	// TODO(nick): This type check is not complete and should be revisited once
   569  	// https://github.com/golang/go/issues/39717 lands. It is currently impractical to
   570  	// type check Named types as they cannot be asserted.
   571  
   572  	if n.typ.TypeOf().Kind() != reflect.Interface {
   573  		return n.cfgErrorf("invalid type assertion: non-interface type %s on left", n.typ.id())
   574  	}
   575  	ims := n.typ.methods()
   576  	if len(ims) == 0 {
   577  		// Empty interface must be a dynamic check.
   578  		return nil
   579  	}
   580  
   581  	if isInterface(typ) {
   582  		// Asserting to an interface is a dynamic check as we must look to the
   583  		// underlying struct.
   584  		return nil
   585  	}
   586  
   587  	for name := range ims {
   588  		im := lookupFieldOrMethod(n.typ, name)
   589  		tm := lookupFieldOrMethod(typ, name)
   590  		if im == nil {
   591  			// This should not be possible.
   592  			continue
   593  		}
   594  		if tm == nil {
   595  			// Lookup for non-exported methods is impossible
   596  			// for bin types, ignore them as they can't be used
   597  			// directly by the interpreted programs.
   598  			if !token.IsExported(name) && isBin(typ) {
   599  				continue
   600  			}
   601  			return n.cfgErrorf("impossible type assertion: %s does not implement %s (missing %v method)", typ.id(), n.typ.id(), name)
   602  		}
   603  		if tm.recv != nil && tm.recv.TypeOf().Kind() == reflect.Ptr && typ.TypeOf().Kind() != reflect.Ptr {
   604  			return n.cfgErrorf("impossible type assertion: %s does not implement %s as %q method has a pointer receiver", typ.id(), n.typ.id(), name)
   605  		}
   606  
   607  		err := n.cfgErrorf("impossible type assertion: %s does not implement %s", typ.id(), n.typ.id())
   608  		if im.numIn() != tm.numIn() || im.numOut() != tm.numOut() {
   609  			return err
   610  		}
   611  		for i := 0; i < im.numIn(); i++ {
   612  			if !im.in(i).equals(tm.in(i)) {
   613  				return err
   614  			}
   615  		}
   616  		for i := 0; i < im.numOut(); i++ {
   617  			if !im.out(i).equals(tm.out(i)) {
   618  				return err
   619  			}
   620  		}
   621  	}
   622  	return nil
   623  }
   624  
   625  // conversion type checks the conversion of n to typ.
   626  func (check typecheck) conversion(n *node, typ *itype) error {
   627  	var c constant.Value
   628  	if n.rval.IsValid() {
   629  		if con, ok := n.rval.Interface().(constant.Value); ok {
   630  			c = con
   631  		}
   632  	}
   633  
   634  	var ok bool
   635  	switch {
   636  	case c != nil && isConstType(typ):
   637  		switch t := typ.TypeOf(); {
   638  		case representableConst(c, t):
   639  			ok = true
   640  		case isInt(n.typ.TypeOf()) && isString(t):
   641  			codepoint := int64(-1)
   642  			if i, ok := constant.Int64Val(c); ok {
   643  				codepoint = i
   644  			}
   645  			n.rval = reflect.ValueOf(constant.MakeString(string(rune(codepoint))))
   646  			ok = true
   647  		}
   648  
   649  	case n.typ.convertibleTo(typ):
   650  		ok = true
   651  	}
   652  	if !ok {
   653  		return n.cfgErrorf("cannot convert expression of type %s to type %s", n.typ.id(), typ.id())
   654  	}
   655  	if !n.typ.untyped || c == nil {
   656  		return nil
   657  	}
   658  	if isInterface(typ) || !isConstType(typ) {
   659  		typ = n.typ.defaultType(n.rval, check.scope)
   660  	}
   661  	return check.convertUntyped(n, typ)
   662  }
   663  
   664  type param struct {
   665  	nod *node
   666  	typ *itype
   667  }
   668  
   669  func (p param) Type() *itype {
   670  	if p.typ != nil {
   671  		return p.typ
   672  	}
   673  	return p.nod.typ
   674  }
   675  
   676  // unpackParams unpacks child parameters into a slice of param.
   677  // If there is only 1 child and it is a callExpr with an n-value return,
   678  // the return types are returned, otherwise the original child nodes are
   679  // returned with nil typ.
   680  func (check typecheck) unpackParams(child []*node) (params []param) {
   681  	if len(child) == 1 && isCall(child[0]) && child[0].child[0].typ.numOut() > 1 {
   682  		c0 := child[0]
   683  		ftyp := child[0].child[0].typ
   684  		for i := 0; i < ftyp.numOut(); i++ {
   685  			params = append(params, param{nod: c0, typ: ftyp.out(i)})
   686  		}
   687  		return params
   688  	}
   689  
   690  	for _, c := range child {
   691  		params = append(params, param{nod: c})
   692  	}
   693  	return params
   694  }
   695  
   696  var builtinFuncs = map[string]struct {
   697  	args     int
   698  	variadic bool
   699  }{
   700  	bltnAppend:  {args: 1, variadic: true},
   701  	bltnCap:     {args: 1, variadic: false},
   702  	bltnClose:   {args: 1, variadic: false},
   703  	bltnComplex: {args: 2, variadic: false},
   704  	bltnImag:    {args: 1, variadic: false},
   705  	bltnCopy:    {args: 2, variadic: false},
   706  	bltnDelete:  {args: 2, variadic: false},
   707  	bltnLen:     {args: 1, variadic: false},
   708  	bltnMake:    {args: 1, variadic: true},
   709  	bltnNew:     {args: 1, variadic: false},
   710  	bltnPanic:   {args: 1, variadic: false},
   711  	bltnPrint:   {args: 0, variadic: true},
   712  	bltnPrintln: {args: 0, variadic: true},
   713  	bltnReal:    {args: 1, variadic: false},
   714  	bltnRecover: {args: 0, variadic: false},
   715  }
   716  
   717  func (check typecheck) builtin(name string, n *node, child []*node, ellipsis bool) error {
   718  	fun := builtinFuncs[name]
   719  	if ellipsis && name != bltnAppend {
   720  		return n.cfgErrorf("invalid use of ... with builtin %s", name)
   721  	}
   722  
   723  	var params []param
   724  	nparams := len(child)
   725  	switch name {
   726  	case bltnMake, bltnNew:
   727  		// Special param handling
   728  	default:
   729  		params = check.unpackParams(child)
   730  		nparams = len(params)
   731  	}
   732  
   733  	if nparams < fun.args {
   734  		return n.cfgErrorf("not enough arguments in call to %s", name)
   735  	} else if !fun.variadic && nparams > fun.args {
   736  		return n.cfgErrorf("too many arguments for %s", name)
   737  	}
   738  
   739  	switch name {
   740  	case bltnAppend:
   741  		typ := params[0].Type()
   742  		t := typ.TypeOf()
   743  		if t == nil || t.Kind() != reflect.Slice {
   744  			return params[0].nod.cfgErrorf("first argument to append must be slice; have %s", typ.id())
   745  		}
   746  
   747  		if nparams == 1 {
   748  			return nil
   749  		}
   750  		// Special case append([]byte, "test"...) is allowed.
   751  		t1 := params[1].Type()
   752  		if nparams == 2 && ellipsis && t.Elem().Kind() == reflect.Uint8 && t1.TypeOf().Kind() == reflect.String {
   753  			if t1.untyped {
   754  				return check.convertUntyped(params[1].nod, check.scope.getType("string"))
   755  			}
   756  			return nil
   757  		}
   758  
   759  		fun := &node{
   760  			typ: &itype{
   761  				cat: funcT,
   762  				arg: []*itype{
   763  					typ,
   764  					{cat: variadicT, val: valueTOf(t.Elem())},
   765  				},
   766  				ret: []*itype{typ},
   767  			},
   768  			ident: "append",
   769  		}
   770  		return check.arguments(n, child, fun, ellipsis)
   771  	case bltnCap, bltnLen:
   772  		typ := arrayDeref(params[0].Type())
   773  		ok := false
   774  		switch typ.TypeOf().Kind() {
   775  		case reflect.Array, reflect.Slice, reflect.Chan:
   776  			ok = true
   777  		case reflect.String, reflect.Map:
   778  			ok = name == bltnLen
   779  		}
   780  		if !ok {
   781  			return params[0].nod.cfgErrorf("invalid argument for %s", name)
   782  		}
   783  	case bltnClose:
   784  		p := params[0]
   785  		typ := p.Type()
   786  		t := typ.TypeOf()
   787  		if t.Kind() != reflect.Chan {
   788  			return p.nod.cfgErrorf("invalid operation: non-chan type %s", p.nod.typ.id())
   789  		}
   790  		if t.ChanDir() == reflect.RecvDir {
   791  			return p.nod.cfgErrorf("invalid operation: cannot close receive-only channel")
   792  		}
   793  	case bltnComplex:
   794  		var err error
   795  		p0, p1 := params[0], params[1]
   796  		typ0, typ1 := p0.Type(), p1.Type()
   797  		switch {
   798  		case typ0.untyped && !typ1.untyped:
   799  			err = check.convertUntyped(p0.nod, typ1)
   800  		case !typ0.untyped && typ1.untyped:
   801  			err = check.convertUntyped(p1.nod, typ0)
   802  		case typ0.untyped && typ1.untyped:
   803  			fltType := check.scope.getType("float64")
   804  			err = check.convertUntyped(p0.nod, fltType)
   805  			if err != nil {
   806  				break
   807  			}
   808  			err = check.convertUntyped(p1.nod, fltType)
   809  		}
   810  		if err != nil {
   811  			return err
   812  		}
   813  
   814  		// check we have the correct types after conversion.
   815  		typ0, typ1 = p0.Type(), p1.Type()
   816  		if !typ0.equals(typ1) {
   817  			return n.cfgErrorf("invalid operation: mismatched types %s and %s", typ0.id(), typ1.id())
   818  		}
   819  		if !isFloat(typ0.TypeOf()) {
   820  			return n.cfgErrorf("invalid operation: arguments have type %s, expected floating-point", typ0.id())
   821  		}
   822  	case bltnImag, bltnReal:
   823  		p := params[0]
   824  		typ := p.Type()
   825  		if typ.untyped {
   826  			if err := check.convertUntyped(p.nod, check.scope.getType("complex128")); err != nil {
   827  				return err
   828  			}
   829  		}
   830  		typ = p.Type()
   831  		if !isComplex(typ.TypeOf()) {
   832  			return p.nod.cfgErrorf("invalid argument type %s for %s", typ.id(), name)
   833  		}
   834  	case bltnCopy:
   835  		typ0, typ1 := params[0].Type(), params[1].Type()
   836  		var t0, t1 reflect.Type
   837  		if t := typ0.TypeOf(); t.Kind() == reflect.Slice {
   838  			t0 = t.Elem()
   839  		}
   840  
   841  		switch t := typ1.TypeOf(); t.Kind() {
   842  		case reflect.String:
   843  			t1 = reflect.TypeOf(byte(1))
   844  		case reflect.Slice:
   845  			t1 = t.Elem()
   846  		}
   847  
   848  		if t0 == nil || t1 == nil {
   849  			return n.cfgErrorf("copy expects slice arguments")
   850  		}
   851  		if !reflect.DeepEqual(t0, t1) {
   852  			return n.cfgErrorf("arguments to copy have different element types %s and %s", typ0.id(), typ1.id())
   853  		}
   854  	case bltnDelete:
   855  		typ := params[0].Type()
   856  		if typ.TypeOf().Kind() != reflect.Map {
   857  			return params[0].nod.cfgErrorf("first argument to delete must be map; have %s", typ.id())
   858  		}
   859  		ktyp := params[1].Type()
   860  		if typ.key != nil && !ktyp.assignableTo(typ.key) {
   861  			return params[1].nod.cfgErrorf("cannot use %s as type %s in delete", ktyp.id(), typ.key.id())
   862  		}
   863  	case bltnMake:
   864  		var min int
   865  		switch child[0].typ.TypeOf().Kind() {
   866  		case reflect.Slice:
   867  			min = 2
   868  		case reflect.Map, reflect.Chan:
   869  			min = 1
   870  		default:
   871  			return child[0].cfgErrorf("cannot make %s; type must be slice, map, or channel", child[0].typ.id())
   872  		}
   873  		if nparams < min {
   874  			return n.cfgErrorf("not enough arguments in call to make")
   875  		} else if nparams > min+1 {
   876  			return n.cfgErrorf("too many arguments for make")
   877  		}
   878  
   879  		var sizes []int
   880  		for _, c := range child[1:] {
   881  			if err := check.index(c, -1); err != nil {
   882  				return err
   883  			}
   884  			if c.rval.IsValid() {
   885  				sizes = append(sizes, int(vInt(c.rval)))
   886  			}
   887  		}
   888  		for len(sizes) == 2 && sizes[0] > sizes[1] {
   889  			return n.cfgErrorf("len larger than cap in make")
   890  		}
   891  
   892  	case bltnPanic:
   893  		return check.assignment(params[0].nod, check.scope.getType("interface{}"), "argument to panic")
   894  	case bltnPrint, bltnPrintln:
   895  		for _, param := range params {
   896  			if param.typ != nil {
   897  				continue
   898  			}
   899  
   900  			if err := check.assignment(param.nod, nil, "argument to "+name); err != nil {
   901  				return err
   902  			}
   903  		}
   904  	case bltnRecover, bltnNew:
   905  		// Nothing to do.
   906  	default:
   907  		return n.cfgErrorf("unsupported builtin %s", name)
   908  	}
   909  	return nil
   910  }
   911  
   912  // arrayDeref returns A if typ is *A, otherwise typ.
   913  func arrayDeref(typ *itype) *itype {
   914  	if typ.cat == valueT && typ.TypeOf().Kind() == reflect.Ptr {
   915  		t := typ.TypeOf()
   916  		if t.Elem().Kind() == reflect.Array {
   917  			return valueTOf(t.Elem())
   918  		}
   919  		return typ
   920  	}
   921  
   922  	if typ.cat == ptrT && typ.val.cat == arrayT {
   923  		return typ.val
   924  	}
   925  	return typ
   926  }
   927  
   928  // arguments type checks the call expression arguments.
   929  func (check typecheck) arguments(n *node, child []*node, fun *node, ellipsis bool) error {
   930  	params := check.unpackParams(child)
   931  	l := len(child)
   932  	if ellipsis {
   933  		if !fun.typ.isVariadic() {
   934  			return n.cfgErrorf("invalid use of ..., corresponding parameter is non-variadic")
   935  		}
   936  		if len(params) > l {
   937  			return child[0].cfgErrorf("cannot use ... with %d-valued %s", child[0].child[0].typ.numOut(), child[0].child[0].typ.id())
   938  		}
   939  	}
   940  
   941  	var cnt int
   942  	for i, param := range params {
   943  		ellip := i == l-1 && ellipsis
   944  		if err := check.argument(param, fun.typ, cnt, l, ellip); err != nil {
   945  			return err
   946  		}
   947  		cnt++
   948  	}
   949  
   950  	if fun.typ.isVariadic() {
   951  		cnt++
   952  	}
   953  	if cnt < fun.typ.numIn() {
   954  		return n.cfgErrorf("not enough arguments in call to %s", fun.name())
   955  	}
   956  	return nil
   957  }
   958  
   959  func (check typecheck) argument(p param, ftyp *itype, i, l int, ellipsis bool) error {
   960  	atyp := getArg(ftyp, i)
   961  	if atyp == nil {
   962  		return p.nod.cfgErrorf("too many arguments")
   963  	}
   964  
   965  	if p.typ == nil && isCall(p.nod) && p.nod.child[0].typ.numOut() != 1 {
   966  		if l == 1 {
   967  			return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp))
   968  		}
   969  		return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), atyp.id())
   970  	}
   971  
   972  	if ellipsis {
   973  		if i != ftyp.numIn()-1 {
   974  			return p.nod.cfgErrorf("can only use ... with matching parameter")
   975  		}
   976  		t := p.Type().TypeOf()
   977  		if t.Kind() != reflect.Slice || !(valueTOf(t.Elem())).assignableTo(atyp) {
   978  			return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.typ.id(), (sliceOf(atyp)).id())
   979  		}
   980  		return nil
   981  	}
   982  
   983  	if p.typ != nil {
   984  		if !p.typ.assignableTo(atyp) {
   985  			return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp))
   986  		}
   987  		return nil
   988  	}
   989  	return check.assignment(p.nod, atyp, "")
   990  }
   991  
   992  func getArg(ftyp *itype, i int) *itype {
   993  	l := ftyp.numIn()
   994  	switch {
   995  	case ftyp.isVariadic() && i >= l-1:
   996  		arg := ftyp.in(l - 1).val
   997  		return arg
   998  	case i < l:
   999  		return ftyp.in(i)
  1000  	case ftyp.cat == valueT && i < ftyp.rtype.NumIn():
  1001  		return valueTOf(ftyp.rtype.In(i))
  1002  	default:
  1003  		return nil
  1004  	}
  1005  }
  1006  
  1007  func getArgsID(ftyp *itype) string {
  1008  	res := "("
  1009  	for i, arg := range ftyp.arg {
  1010  		if i > 0 {
  1011  			res += ","
  1012  		}
  1013  		res += arg.id()
  1014  	}
  1015  	res += ")"
  1016  	return res
  1017  }
  1018  
  1019  var errCantConvert = errors.New("cannot convert")
  1020  
  1021  func (check typecheck) convertUntyped(n *node, typ *itype) error {
  1022  	if n.typ == nil || !n.typ.untyped || typ == nil {
  1023  		return nil
  1024  	}
  1025  
  1026  	convErr := n.cfgErrorf("cannot convert %s to %s", n.typ.id(), typ.id())
  1027  
  1028  	ntyp, ttyp := n.typ.TypeOf(), typ.TypeOf()
  1029  	if typ.untyped {
  1030  		// Both n and target are untyped.
  1031  		nkind, tkind := ntyp.Kind(), ttyp.Kind()
  1032  		if isNumber(ntyp) && isNumber(ttyp) {
  1033  			if nkind < tkind {
  1034  				n.typ = typ
  1035  			}
  1036  		} else if nkind != tkind {
  1037  			return convErr
  1038  		}
  1039  		return nil
  1040  	}
  1041  
  1042  	var (
  1043  		ityp *itype
  1044  		rtyp reflect.Type
  1045  		err  error
  1046  	)
  1047  	switch {
  1048  	case typ.isNil() && n.typ.isNil():
  1049  		n.typ = typ
  1050  		return nil
  1051  	case isNumber(ttyp) || isString(ttyp) || isBoolean(ttyp):
  1052  		ityp = typ
  1053  		rtyp = ttyp
  1054  	case isInterface(typ):
  1055  		if n.typ.isNil() {
  1056  			return nil
  1057  		}
  1058  		if len(n.typ.methods()) > 0 { // untyped cannot be set to iface
  1059  			return convErr
  1060  		}
  1061  		ityp = n.typ.defaultType(n.rval, check.scope)
  1062  		rtyp = ntyp
  1063  	case isArray(typ) || isMap(typ) || isChan(typ) || isFunc(typ) || isPtr(typ):
  1064  		// TODO(nick): above we are acting on itype, but really it is an rtype check. This is not clear which type
  1065  		// 		 	   plain we are in. Fix this later.
  1066  		if !n.typ.isNil() {
  1067  			return convErr
  1068  		}
  1069  		return nil
  1070  	default:
  1071  		return convErr
  1072  	}
  1073  
  1074  	if err := check.representable(n, rtyp); err != nil {
  1075  		return err
  1076  	}
  1077  	n.rval, err = check.convertConst(n.rval, rtyp)
  1078  	if err != nil {
  1079  		if errors.Is(err, errCantConvert) {
  1080  			return convErr
  1081  		}
  1082  		return n.cfgErrorf(err.Error())
  1083  	}
  1084  	n.typ = ityp
  1085  	return nil
  1086  }
  1087  
  1088  func (check typecheck) representable(n *node, t reflect.Type) error {
  1089  	if !n.rval.IsValid() {
  1090  		// TODO(nick): This should be an error as the const is in the frame which is undesirable.
  1091  		return nil
  1092  	}
  1093  	c, ok := n.rval.Interface().(constant.Value)
  1094  	if !ok {
  1095  		// TODO(nick): This should be an error as untyped strings and bools should be constant.Values.
  1096  		return nil
  1097  	}
  1098  
  1099  	if !representableConst(c, t) {
  1100  		typ := n.typ.TypeOf()
  1101  		if isNumber(typ) && isNumber(t) {
  1102  			// numeric conversion : error msg
  1103  			//
  1104  			// integer -> integer : overflows
  1105  			// integer -> float   : overflows (actually not possible)
  1106  			// float   -> integer : truncated
  1107  			// float   -> float   : overflows
  1108  			//
  1109  			if !isInt(typ) && isInt(t) {
  1110  				return n.cfgErrorf("%s truncated to %s", c.ExactString(), t.Kind().String())
  1111  			}
  1112  			return n.cfgErrorf("%s overflows %s", c.ExactString(), t.Kind().String())
  1113  		}
  1114  		return n.cfgErrorf("cannot convert %s to %s", c.ExactString(), t.Kind().String())
  1115  	}
  1116  	return nil
  1117  }
  1118  
  1119  func (check typecheck) convertConst(v reflect.Value, t reflect.Type) (reflect.Value, error) {
  1120  	if !v.IsValid() {
  1121  		// TODO(nick): This should be an error as the const is in the frame which is undesirable.
  1122  		return v, nil
  1123  	}
  1124  	c, ok := v.Interface().(constant.Value)
  1125  	if !ok {
  1126  		// TODO(nick): This should be an error as untyped strings and bools should be constant.Values.
  1127  		return v, nil
  1128  	}
  1129  
  1130  	kind := t.Kind()
  1131  	switch kind {
  1132  	case reflect.Bool:
  1133  		v = reflect.ValueOf(constant.BoolVal(c))
  1134  	case reflect.String:
  1135  		v = reflect.ValueOf(constant.StringVal(c))
  1136  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1137  		i, _ := constant.Int64Val(constant.ToInt(c))
  1138  		v = reflect.ValueOf(i).Convert(t)
  1139  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1140  		i, _ := constant.Uint64Val(constant.ToInt(c))
  1141  		v = reflect.ValueOf(i).Convert(t)
  1142  	case reflect.Float32:
  1143  		f, _ := constant.Float32Val(constant.ToFloat(c))
  1144  		v = reflect.ValueOf(f)
  1145  	case reflect.Float64:
  1146  		f, _ := constant.Float64Val(constant.ToFloat(c))
  1147  		v = reflect.ValueOf(f)
  1148  	case reflect.Complex64:
  1149  		r, _ := constant.Float32Val(constant.Real(c))
  1150  		i, _ := constant.Float32Val(constant.Imag(c))
  1151  		v = reflect.ValueOf(complex(r, i)).Convert(t)
  1152  	case reflect.Complex128:
  1153  		r, _ := constant.Float64Val(constant.Real(c))
  1154  		i, _ := constant.Float64Val(constant.Imag(c))
  1155  		v = reflect.ValueOf(complex(r, i)).Convert(t)
  1156  	default:
  1157  		return v, errCantConvert
  1158  	}
  1159  	return v, nil
  1160  }
  1161  
  1162  var bitlen = [...]int{
  1163  	reflect.Int:     64,
  1164  	reflect.Int8:    8,
  1165  	reflect.Int16:   16,
  1166  	reflect.Int32:   32,
  1167  	reflect.Int64:   64,
  1168  	reflect.Uint:    64,
  1169  	reflect.Uint8:   8,
  1170  	reflect.Uint16:  16,
  1171  	reflect.Uint32:  32,
  1172  	reflect.Uint64:  64,
  1173  	reflect.Uintptr: 64,
  1174  }
  1175  
  1176  func representableConst(c constant.Value, t reflect.Type) bool {
  1177  	switch {
  1178  	case isInt(t):
  1179  		x := constant.ToInt(c)
  1180  		if x.Kind() != constant.Int {
  1181  			return false
  1182  		}
  1183  		switch t.Kind() {
  1184  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1185  			if _, ok := constant.Int64Val(x); !ok {
  1186  				return false
  1187  			}
  1188  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1189  			if _, ok := constant.Uint64Val(x); !ok {
  1190  				return false
  1191  			}
  1192  		default:
  1193  			return false
  1194  		}
  1195  		return constant.BitLen(x) <= bitlen[t.Kind()]
  1196  	case isFloat(t):
  1197  		x := constant.ToFloat(c)
  1198  		if x.Kind() != constant.Float {
  1199  			return false
  1200  		}
  1201  		switch t.Kind() {
  1202  		case reflect.Float32:
  1203  			f, _ := constant.Float32Val(x)
  1204  			return !math.IsInf(float64(f), 0)
  1205  		case reflect.Float64:
  1206  			f, _ := constant.Float64Val(x)
  1207  			return !math.IsInf(f, 0)
  1208  		default:
  1209  			return false
  1210  		}
  1211  	case isComplex(t):
  1212  		x := constant.ToComplex(c)
  1213  		if x.Kind() != constant.Complex {
  1214  			return false
  1215  		}
  1216  		switch t.Kind() {
  1217  		case reflect.Complex64:
  1218  			r, _ := constant.Float32Val(constant.Real(x))
  1219  			i, _ := constant.Float32Val(constant.Imag(x))
  1220  			return !math.IsInf(float64(r), 0) && !math.IsInf(float64(i), 0)
  1221  		case reflect.Complex128:
  1222  			r, _ := constant.Float64Val(constant.Real(x))
  1223  			i, _ := constant.Float64Val(constant.Imag(x))
  1224  			return !math.IsInf(r, 0) && !math.IsInf(i, 0)
  1225  		default:
  1226  			return false
  1227  		}
  1228  	case isString(t):
  1229  		return c.Kind() == constant.String
  1230  	case isBoolean(t):
  1231  		return c.Kind() == constant.Bool
  1232  	default:
  1233  		return false
  1234  	}
  1235  }
  1236  
  1237  func isShiftAction(a action) bool {
  1238  	switch a {
  1239  	case aShl, aShr, aShlAssign, aShrAssign:
  1240  		return true
  1241  	}
  1242  	return false
  1243  }
  1244  
  1245  func isComparisonAction(a action) bool {
  1246  	switch a {
  1247  	case aEqual, aNotEqual, aGreater, aGreaterEqual, aLower, aLowerEqual:
  1248  		return true
  1249  	}
  1250  	return false
  1251  }