...
Run Format

Source file src/go/types/builtins.go

Documentation: go/types

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file implements typechecking of builtin function calls.
     6  
     7  package types
     8  
     9  import (
    10  	"go/ast"
    11  	"go/constant"
    12  	"go/token"
    13  )
    14  
    15  // builtin type-checks a call to the built-in specified by id and
    16  // returns true if the call is valid, with *x holding the result;
    17  // but x.expr is not set. If the call is invalid, the result is
    18  // false, and *x is undefined.
    19  //
    20  func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
    21  	// append is the only built-in that permits the use of ... for the last argument
    22  	bin := predeclaredFuncs[id]
    23  	if call.Ellipsis.IsValid() && id != _Append {
    24  		check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
    25  		check.use(call.Args...)
    26  		return
    27  	}
    28  
    29  	// For len(x) and cap(x) we need to know if x contains any function calls or
    30  	// receive operations. Save/restore current setting and set hasCallOrRecv to
    31  	// false for the evaluation of x so that we can check it afterwards.
    32  	// Note: We must do this _before_ calling unpack because unpack evaluates the
    33  	//       first argument before we even call arg(x, 0)!
    34  	if id == _Len || id == _Cap {
    35  		defer func(b bool) {
    36  			check.hasCallOrRecv = b
    37  		}(check.hasCallOrRecv)
    38  		check.hasCallOrRecv = false
    39  	}
    40  
    41  	// determine actual arguments
    42  	var arg getter
    43  	nargs := len(call.Args)
    44  	switch id {
    45  	default:
    46  		// make argument getter
    47  		arg, nargs, _ = unpack(func(x *operand, i int) { check.multiExpr(x, call.Args[i]) }, nargs, false)
    48  		if arg == nil {
    49  			return
    50  		}
    51  		// evaluate first argument, if present
    52  		if nargs > 0 {
    53  			arg(x, 0)
    54  			if x.mode == invalid {
    55  				return
    56  			}
    57  		}
    58  	case _Make, _New, _Offsetof, _Trace:
    59  		// arguments require special handling
    60  	}
    61  
    62  	// check argument count
    63  	{
    64  		msg := ""
    65  		if nargs < bin.nargs {
    66  			msg = "not enough"
    67  		} else if !bin.variadic && nargs > bin.nargs {
    68  			msg = "too many"
    69  		}
    70  		if msg != "" {
    71  			check.invalidOp(call.Rparen, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
    72  			return
    73  		}
    74  	}
    75  
    76  	switch id {
    77  	case _Append:
    78  		// append(s S, x ...T) S, where T is the element type of S
    79  		// spec: "The variadic function append appends zero or more values x to s of type
    80  		// S, which must be a slice type, and returns the resulting slice, also of type S.
    81  		// The values x are passed to a parameter of type ...T where T is the element type
    82  		// of S and the respective parameter passing rules apply."
    83  		S := x.typ
    84  		var T Type
    85  		if s, _ := S.Underlying().(*Slice); s != nil {
    86  			T = s.elem
    87  		} else {
    88  			check.invalidArg(x.pos(), "%s is not a slice", x)
    89  			return
    90  		}
    91  
    92  		// remember arguments that have been evaluated already
    93  		alist := []operand{*x}
    94  
    95  		// spec: "As a special case, append also accepts a first argument assignable
    96  		// to type []byte with a second argument of string type followed by ... .
    97  		// This form appends the bytes of the string.
    98  		if nargs == 2 && call.Ellipsis.IsValid() && x.assignableTo(check.conf, NewSlice(universeByte), nil) {
    99  			arg(x, 1)
   100  			if x.mode == invalid {
   101  				return
   102  			}
   103  			if isString(x.typ) {
   104  				if check.Types != nil {
   105  					sig := makeSig(S, S, x.typ)
   106  					sig.variadic = true
   107  					check.recordBuiltinType(call.Fun, sig)
   108  				}
   109  				x.mode = value
   110  				x.typ = S
   111  				break
   112  			}
   113  			alist = append(alist, *x)
   114  			// fallthrough
   115  		}
   116  
   117  		// check general case by creating custom signature
   118  		sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
   119  		sig.variadic = true
   120  		check.arguments(x, call, sig, func(x *operand, i int) {
   121  			// only evaluate arguments that have not been evaluated before
   122  			if i < len(alist) {
   123  				*x = alist[i]
   124  				return
   125  			}
   126  			arg(x, i)
   127  		}, nargs)
   128  		// ok to continue even if check.arguments reported errors
   129  
   130  		x.mode = value
   131  		x.typ = S
   132  		if check.Types != nil {
   133  			check.recordBuiltinType(call.Fun, sig)
   134  		}
   135  
   136  	case _Cap, _Len:
   137  		// cap(x)
   138  		// len(x)
   139  		mode := invalid
   140  		var typ Type
   141  		var val constant.Value
   142  		switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) {
   143  		case *Basic:
   144  			if isString(t) && id == _Len {
   145  				if x.mode == constant_ {
   146  					mode = constant_
   147  					val = constant.MakeInt64(int64(len(constant.StringVal(x.val))))
   148  				} else {
   149  					mode = value
   150  				}
   151  			}
   152  
   153  		case *Array:
   154  			mode = value
   155  			// spec: "The expressions len(s) and cap(s) are constants
   156  			// if the type of s is an array or pointer to an array and
   157  			// the expression s does not contain channel receives or
   158  			// function calls; in this case s is not evaluated."
   159  			if !check.hasCallOrRecv {
   160  				mode = constant_
   161  				if t.len >= 0 {
   162  					val = constant.MakeInt64(t.len)
   163  				} else {
   164  					val = constant.MakeUnknown()
   165  				}
   166  			}
   167  
   168  		case *Slice, *Chan:
   169  			mode = value
   170  
   171  		case *Map:
   172  			if id == _Len {
   173  				mode = value
   174  			}
   175  		}
   176  
   177  		if mode == invalid && typ != Typ[Invalid] {
   178  			check.invalidArg(x.pos(), "%s for %s", x, bin.name)
   179  			return
   180  		}
   181  
   182  		x.mode = mode
   183  		x.typ = Typ[Int]
   184  		x.val = val
   185  		if check.Types != nil && mode != constant_ {
   186  			check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
   187  		}
   188  
   189  	case _Close:
   190  		// close(c)
   191  		c, _ := x.typ.Underlying().(*Chan)
   192  		if c == nil {
   193  			check.invalidArg(x.pos(), "%s is not a channel", x)
   194  			return
   195  		}
   196  		if c.dir == RecvOnly {
   197  			check.invalidArg(x.pos(), "%s must not be a receive-only channel", x)
   198  			return
   199  		}
   200  
   201  		x.mode = novalue
   202  		if check.Types != nil {
   203  			check.recordBuiltinType(call.Fun, makeSig(nil, c))
   204  		}
   205  
   206  	case _Complex:
   207  		// complex(x, y floatT) complexT
   208  		var y operand
   209  		arg(&y, 1)
   210  		if y.mode == invalid {
   211  			return
   212  		}
   213  
   214  		// convert or check untyped arguments
   215  		d := 0
   216  		if isUntyped(x.typ) {
   217  			d |= 1
   218  		}
   219  		if isUntyped(y.typ) {
   220  			d |= 2
   221  		}
   222  		switch d {
   223  		case 0:
   224  			// x and y are typed => nothing to do
   225  		case 1:
   226  			// only x is untyped => convert to type of y
   227  			check.convertUntyped(x, y.typ)
   228  		case 2:
   229  			// only y is untyped => convert to type of x
   230  			check.convertUntyped(&y, x.typ)
   231  		case 3:
   232  			// x and y are untyped =>
   233  			// 1) if both are constants, convert them to untyped
   234  			//    floating-point numbers if possible,
   235  			// 2) if one of them is not constant (possible because
   236  			//    it contains a shift that is yet untyped), convert
   237  			//    both of them to float64 since they must have the
   238  			//    same type to succeed (this will result in an error
   239  			//    because shifts of floats are not permitted)
   240  			if x.mode == constant_ && y.mode == constant_ {
   241  				toFloat := func(x *operand) {
   242  					if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
   243  						x.typ = Typ[UntypedFloat]
   244  					}
   245  				}
   246  				toFloat(x)
   247  				toFloat(&y)
   248  			} else {
   249  				check.convertUntyped(x, Typ[Float64])
   250  				check.convertUntyped(&y, Typ[Float64])
   251  				// x and y should be invalid now, but be conservative
   252  				// and check below
   253  			}
   254  		}
   255  		if x.mode == invalid || y.mode == invalid {
   256  			return
   257  		}
   258  
   259  		// both argument types must be identical
   260  		if !Identical(x.typ, y.typ) {
   261  			check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
   262  			return
   263  		}
   264  
   265  		// the argument types must be of floating-point type
   266  		if !isFloat(x.typ) {
   267  			check.invalidArg(x.pos(), "arguments have type %s, expected floating-point", x.typ)
   268  			return
   269  		}
   270  
   271  		// if both arguments are constants, the result is a constant
   272  		if x.mode == constant_ && y.mode == constant_ {
   273  			x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
   274  		} else {
   275  			x.mode = value
   276  		}
   277  
   278  		// determine result type
   279  		var res BasicKind
   280  		switch x.typ.Underlying().(*Basic).kind {
   281  		case Float32:
   282  			res = Complex64
   283  		case Float64:
   284  			res = Complex128
   285  		case UntypedFloat:
   286  			res = UntypedComplex
   287  		default:
   288  			unreachable()
   289  		}
   290  		resTyp := Typ[res]
   291  
   292  		if check.Types != nil && x.mode != constant_ {
   293  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
   294  		}
   295  
   296  		x.typ = resTyp
   297  
   298  	case _Copy:
   299  		// copy(x, y []T) int
   300  		var dst Type
   301  		if t, _ := x.typ.Underlying().(*Slice); t != nil {
   302  			dst = t.elem
   303  		}
   304  
   305  		var y operand
   306  		arg(&y, 1)
   307  		if y.mode == invalid {
   308  			return
   309  		}
   310  		var src Type
   311  		switch t := y.typ.Underlying().(type) {
   312  		case *Basic:
   313  			if isString(y.typ) {
   314  				src = universeByte
   315  			}
   316  		case *Slice:
   317  			src = t.elem
   318  		}
   319  
   320  		if dst == nil || src == nil {
   321  			check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y)
   322  			return
   323  		}
   324  
   325  		if !Identical(dst, src) {
   326  			check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
   327  			return
   328  		}
   329  
   330  		if check.Types != nil {
   331  			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
   332  		}
   333  		x.mode = value
   334  		x.typ = Typ[Int]
   335  
   336  	case _Delete:
   337  		// delete(m, k)
   338  		m, _ := x.typ.Underlying().(*Map)
   339  		if m == nil {
   340  			check.invalidArg(x.pos(), "%s is not a map", x)
   341  			return
   342  		}
   343  		arg(x, 1) // k
   344  		if x.mode == invalid {
   345  			return
   346  		}
   347  
   348  		if !x.assignableTo(check.conf, m.key, nil) {
   349  			check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
   350  			return
   351  		}
   352  
   353  		x.mode = novalue
   354  		if check.Types != nil {
   355  			check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key))
   356  		}
   357  
   358  	case _Imag, _Real:
   359  		// imag(complexT) floatT
   360  		// real(complexT) floatT
   361  
   362  		// convert or check untyped argument
   363  		if isUntyped(x.typ) {
   364  			if x.mode == constant_ {
   365  				// an untyped constant number can alway be considered
   366  				// as a complex constant
   367  				if isNumeric(x.typ) {
   368  					x.typ = Typ[UntypedComplex]
   369  				}
   370  			} else {
   371  				// an untyped non-constant argument may appear if
   372  				// it contains a (yet untyped non-constant) shift
   373  				// expression: convert it to complex128 which will
   374  				// result in an error (shift of complex value)
   375  				check.convertUntyped(x, Typ[Complex128])
   376  				// x should be invalid now, but be conservative and check
   377  				if x.mode == invalid {
   378  					return
   379  				}
   380  			}
   381  		}
   382  
   383  		// the argument must be of complex type
   384  		if !isComplex(x.typ) {
   385  			check.invalidArg(x.pos(), "argument has type %s, expected complex type", x.typ)
   386  			return
   387  		}
   388  
   389  		// if the argument is a constant, the result is a constant
   390  		if x.mode == constant_ {
   391  			if id == _Real {
   392  				x.val = constant.Real(x.val)
   393  			} else {
   394  				x.val = constant.Imag(x.val)
   395  			}
   396  		} else {
   397  			x.mode = value
   398  		}
   399  
   400  		// determine result type
   401  		var res BasicKind
   402  		switch x.typ.Underlying().(*Basic).kind {
   403  		case Complex64:
   404  			res = Float32
   405  		case Complex128:
   406  			res = Float64
   407  		case UntypedComplex:
   408  			res = UntypedFloat
   409  		default:
   410  			unreachable()
   411  		}
   412  		resTyp := Typ[res]
   413  
   414  		if check.Types != nil && x.mode != constant_ {
   415  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
   416  		}
   417  
   418  		x.typ = resTyp
   419  
   420  	case _Make:
   421  		// make(T, n)
   422  		// make(T, n, m)
   423  		// (no argument evaluated yet)
   424  		arg0 := call.Args[0]
   425  		T := check.typ(arg0)
   426  		if T == Typ[Invalid] {
   427  			return
   428  		}
   429  
   430  		var min int // minimum number of arguments
   431  		switch T.Underlying().(type) {
   432  		case *Slice:
   433  			min = 2
   434  		case *Map, *Chan:
   435  			min = 1
   436  		default:
   437  			check.invalidArg(arg0.Pos(), "cannot make %s; type must be slice, map, or channel", arg0)
   438  			return
   439  		}
   440  		if nargs < min || min+1 < nargs {
   441  			check.errorf(call.Pos(), "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
   442  			return
   443  		}
   444  		var sizes []int64 // constant integer arguments, if any
   445  		for _, arg := range call.Args[1:] {
   446  			if s, ok := check.index(arg, -1); ok && s >= 0 {
   447  				sizes = append(sizes, s)
   448  			}
   449  		}
   450  		if len(sizes) == 2 && sizes[0] > sizes[1] {
   451  			check.invalidArg(call.Args[1].Pos(), "length and capacity swapped")
   452  			// safe to continue
   453  		}
   454  		x.mode = value
   455  		x.typ = T
   456  		if check.Types != nil {
   457  			params := [...]Type{T, Typ[Int], Typ[Int]}
   458  			check.recordBuiltinType(call.Fun, makeSig(x.typ, params[:1+len(sizes)]...))
   459  		}
   460  
   461  	case _New:
   462  		// new(T)
   463  		// (no argument evaluated yet)
   464  		T := check.typ(call.Args[0])
   465  		if T == Typ[Invalid] {
   466  			return
   467  		}
   468  
   469  		x.mode = value
   470  		x.typ = &Pointer{base: T}
   471  		if check.Types != nil {
   472  			check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
   473  		}
   474  
   475  	case _Panic:
   476  		// panic(x)
   477  		// record panic call if inside a function with result parameters
   478  		// (for use in Checker.isTerminating)
   479  		if check.sig != nil && check.sig.results.Len() > 0 {
   480  			// function has result parameters
   481  			p := check.isPanic
   482  			if p == nil {
   483  				// allocate lazily
   484  				p = make(map[*ast.CallExpr]bool)
   485  				check.isPanic = p
   486  			}
   487  			p[call] = true
   488  		}
   489  
   490  		check.assignment(x, &emptyInterface, "argument to panic")
   491  		if x.mode == invalid {
   492  			return
   493  		}
   494  
   495  		x.mode = novalue
   496  		if check.Types != nil {
   497  			check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
   498  		}
   499  
   500  	case _Print, _Println:
   501  		// print(x, y, ...)
   502  		// println(x, y, ...)
   503  		var params []Type
   504  		if nargs > 0 {
   505  			params = make([]Type, nargs)
   506  			for i := 0; i < nargs; i++ {
   507  				if i > 0 {
   508  					arg(x, i) // first argument already evaluated
   509  				}
   510  				check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name)
   511  				if x.mode == invalid {
   512  					// TODO(gri) "use" all arguments?
   513  					return
   514  				}
   515  				params[i] = x.typ
   516  			}
   517  		}
   518  
   519  		x.mode = novalue
   520  		if check.Types != nil {
   521  			check.recordBuiltinType(call.Fun, makeSig(nil, params...))
   522  		}
   523  
   524  	case _Recover:
   525  		// recover() interface{}
   526  		x.mode = value
   527  		x.typ = &emptyInterface
   528  		if check.Types != nil {
   529  			check.recordBuiltinType(call.Fun, makeSig(x.typ))
   530  		}
   531  
   532  	case _Alignof:
   533  		// unsafe.Alignof(x T) uintptr
   534  		check.assignment(x, nil, "argument to unsafe.Alignof")
   535  		if x.mode == invalid {
   536  			return
   537  		}
   538  
   539  		x.mode = constant_
   540  		x.val = constant.MakeInt64(check.conf.alignof(x.typ))
   541  		x.typ = Typ[Uintptr]
   542  		// result is constant - no need to record signature
   543  
   544  	case _Offsetof:
   545  		// unsafe.Offsetof(x T) uintptr, where x must be a selector
   546  		// (no argument evaluated yet)
   547  		arg0 := call.Args[0]
   548  		selx, _ := unparen(arg0).(*ast.SelectorExpr)
   549  		if selx == nil {
   550  			check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
   551  			check.use(arg0)
   552  			return
   553  		}
   554  
   555  		check.expr(x, selx.X)
   556  		if x.mode == invalid {
   557  			return
   558  		}
   559  
   560  		base := derefStructPtr(x.typ)
   561  		sel := selx.Sel.Name
   562  		obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel)
   563  		switch obj.(type) {
   564  		case nil:
   565  			check.invalidArg(x.pos(), "%s has no single field %s", base, sel)
   566  			return
   567  		case *Func:
   568  			// TODO(gri) Using derefStructPtr may result in methods being found
   569  			// that don't actually exist. An error either way, but the error
   570  			// message is confusing. See: https://play.golang.org/p/al75v23kUy ,
   571  			// but go/types reports: "invalid argument: x.m is a method value".
   572  			check.invalidArg(arg0.Pos(), "%s is a method value", arg0)
   573  			return
   574  		}
   575  		if indirect {
   576  			check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, base)
   577  			return
   578  		}
   579  
   580  		// TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)?
   581  		check.recordSelection(selx, FieldVal, base, obj, index, false)
   582  
   583  		offs := check.conf.offsetof(base, index)
   584  		x.mode = constant_
   585  		x.val = constant.MakeInt64(offs)
   586  		x.typ = Typ[Uintptr]
   587  		// result is constant - no need to record signature
   588  
   589  	case _Sizeof:
   590  		// unsafe.Sizeof(x T) uintptr
   591  		check.assignment(x, nil, "argument to unsafe.Sizeof")
   592  		if x.mode == invalid {
   593  			return
   594  		}
   595  
   596  		x.mode = constant_
   597  		x.val = constant.MakeInt64(check.conf.sizeof(x.typ))
   598  		x.typ = Typ[Uintptr]
   599  		// result is constant - no need to record signature
   600  
   601  	case _Assert:
   602  		// assert(pred) causes a typechecker error if pred is false.
   603  		// The result of assert is the value of pred if there is no error.
   604  		// Note: assert is only available in self-test mode.
   605  		if x.mode != constant_ || !isBoolean(x.typ) {
   606  			check.invalidArg(x.pos(), "%s is not a boolean constant", x)
   607  			return
   608  		}
   609  		if x.val.Kind() != constant.Bool {
   610  			check.errorf(x.pos(), "internal error: value of %s should be a boolean constant", x)
   611  			return
   612  		}
   613  		if !constant.BoolVal(x.val) {
   614  			check.errorf(call.Pos(), "%v failed", call)
   615  			// compile-time assertion failure - safe to continue
   616  		}
   617  		// result is constant - no need to record signature
   618  
   619  	case _Trace:
   620  		// trace(x, y, z, ...) dumps the positions, expressions, and
   621  		// values of its arguments. The result of trace is the value
   622  		// of the first argument.
   623  		// Note: trace is only available in self-test mode.
   624  		// (no argument evaluated yet)
   625  		if nargs == 0 {
   626  			check.dump("%v: trace() without arguments", call.Pos())
   627  			x.mode = novalue
   628  			break
   629  		}
   630  		var t operand
   631  		x1 := x
   632  		for _, arg := range call.Args {
   633  			check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
   634  			check.dump("%v: %s", x1.pos(), x1)
   635  			x1 = &t // use incoming x only for first argument
   636  		}
   637  		// trace is only available in test mode - no need to record signature
   638  
   639  	default:
   640  		unreachable()
   641  	}
   642  
   643  	return true
   644  }
   645  
   646  // makeSig makes a signature for the given argument and result types.
   647  // Default types are used for untyped arguments, and res may be nil.
   648  func makeSig(res Type, args ...Type) *Signature {
   649  	list := make([]*Var, len(args))
   650  	for i, param := range args {
   651  		list[i] = NewVar(token.NoPos, nil, "", Default(param))
   652  	}
   653  	params := NewTuple(list...)
   654  	var result *Tuple
   655  	if res != nil {
   656  		assert(!isUntyped(res))
   657  		result = NewTuple(NewVar(token.NoPos, nil, "", res))
   658  	}
   659  	return &Signature{params: params, results: result}
   660  }
   661  
   662  // implicitArrayDeref returns A if typ is of the form *A and A is an array;
   663  // otherwise it returns typ.
   664  //
   665  func implicitArrayDeref(typ Type) Type {
   666  	if p, ok := typ.(*Pointer); ok {
   667  		if a, ok := p.base.Underlying().(*Array); ok {
   668  			return a
   669  		}
   670  	}
   671  	return typ
   672  }
   673  
   674  // unparen returns e with any enclosing parentheses stripped.
   675  func unparen(e ast.Expr) ast.Expr {
   676  	for {
   677  		p, ok := e.(*ast.ParenExpr)
   678  		if !ok {
   679  			return e
   680  		}
   681  		e = p.X
   682  	}
   683  }
   684  

View as plain text