Black Lives Matter. Support the Equal Justice Initiative.

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  // reports whether 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(atPos(call.Ellipsis),
    25  			_InvalidDotDotDot,
    26  			"invalid use of ... with built-in %s", bin.name)
    27  		check.use(call.Args...)
    28  		return
    29  	}
    30  
    31  	// For len(x) and cap(x) we need to know if x contains any function calls or
    32  	// receive operations. Save/restore current setting and set hasCallOrRecv to
    33  	// false for the evaluation of x so that we can check it afterwards.
    34  	// Note: We must do this _before_ calling exprList because exprList evaluates
    35  	//       all arguments.
    36  	if id == _Len || id == _Cap {
    37  		defer func(b bool) {
    38  			check.hasCallOrRecv = b
    39  		}(check.hasCallOrRecv)
    40  		check.hasCallOrRecv = false
    41  	}
    42  
    43  	// determine actual arguments
    44  	var arg func(*operand, int) // TODO(gri) remove use of arg getter in favor of using xlist directly
    45  	nargs := len(call.Args)
    46  	switch id {
    47  	default:
    48  		// make argument getter
    49  		xlist, _ := check.exprList(call.Args, false)
    50  		arg = func(x *operand, i int) { *x = *xlist[i]; x.typ = expand(x.typ) }
    51  		nargs = len(xlist)
    52  		// evaluate first argument, if present
    53  		if nargs > 0 {
    54  			arg(x, 0)
    55  			if x.mode == invalid {
    56  				return
    57  			}
    58  		}
    59  	case _Make, _New, _Offsetof, _Trace:
    60  		// arguments require special handling
    61  	}
    62  
    63  	// check argument count
    64  	{
    65  		msg := ""
    66  		if nargs < bin.nargs {
    67  			msg = "not enough"
    68  		} else if !bin.variadic && nargs > bin.nargs {
    69  			msg = "too many"
    70  		}
    71  		if msg != "" {
    72  			check.invalidOp(inNode(call, call.Rparen), _WrongArgCount, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
    73  			return
    74  		}
    75  	}
    76  
    77  	switch id {
    78  	case _Append:
    79  		// append(s S, x ...T) S, where T is the element type of S
    80  		// spec: "The variadic function append appends zero or more values x to s of type
    81  		// S, which must be a slice type, and returns the resulting slice, also of type S.
    82  		// The values x are passed to a parameter of type ...T where T is the element type
    83  		// of S and the respective parameter passing rules apply."
    84  		S := x.typ
    85  		var T Type
    86  		if s := asSlice(S); s != nil {
    87  			T = s.elem
    88  		} else {
    89  			check.invalidArg(x, _InvalidAppend, "%s is not a slice", x)
    90  			return
    91  		}
    92  
    93  		// remember arguments that have been evaluated already
    94  		alist := []operand{*x}
    95  
    96  		// spec: "As a special case, append also accepts a first argument assignable
    97  		// to type []byte with a second argument of string type followed by ... .
    98  		// This form appends the bytes of the string.
    99  		if nargs == 2 && call.Ellipsis.IsValid() {
   100  			if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
   101  				arg(x, 1)
   102  				if x.mode == invalid {
   103  					return
   104  				}
   105  				if isString(x.typ) {
   106  					if check.Types != nil {
   107  						sig := makeSig(S, S, x.typ)
   108  						sig.variadic = true
   109  						check.recordBuiltinType(call.Fun, sig)
   110  					}
   111  					x.mode = value
   112  					x.typ = S
   113  					break
   114  				}
   115  				alist = append(alist, *x)
   116  				// fallthrough
   117  			}
   118  		}
   119  
   120  		// check general case by creating custom signature
   121  		sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
   122  		sig.variadic = true
   123  		var xlist []*operand
   124  		// convert []operand to []*operand
   125  		for i := range alist {
   126  			xlist = append(xlist, &alist[i])
   127  		}
   128  		for i := len(alist); i < nargs; i++ {
   129  			var x operand
   130  			arg(&x, i)
   131  			xlist = append(xlist, &x)
   132  		}
   133  		check.arguments(call, sig, nil, xlist) // discard result (we know the result type)
   134  		// ok to continue even if check.arguments reported errors
   135  
   136  		x.mode = value
   137  		x.typ = S
   138  		if check.Types != nil {
   139  			check.recordBuiltinType(call.Fun, sig)
   140  		}
   141  
   142  	case _Cap, _Len:
   143  		// cap(x)
   144  		// len(x)
   145  		mode := invalid
   146  		var typ Type
   147  		var val constant.Value
   148  		switch typ = implicitArrayDeref(optype(x.typ)); t := typ.(type) {
   149  		case *Basic:
   150  			if isString(t) && id == _Len {
   151  				if x.mode == constant_ {
   152  					mode = constant_
   153  					val = constant.MakeInt64(int64(len(constant.StringVal(x.val))))
   154  				} else {
   155  					mode = value
   156  				}
   157  			}
   158  
   159  		case *Array:
   160  			mode = value
   161  			// spec: "The expressions len(s) and cap(s) are constants
   162  			// if the type of s is an array or pointer to an array and
   163  			// the expression s does not contain channel receives or
   164  			// function calls; in this case s is not evaluated."
   165  			if !check.hasCallOrRecv {
   166  				mode = constant_
   167  				if t.len >= 0 {
   168  					val = constant.MakeInt64(t.len)
   169  				} else {
   170  					val = constant.MakeUnknown()
   171  				}
   172  			}
   173  
   174  		case *Slice, *Chan:
   175  			mode = value
   176  
   177  		case *Map:
   178  			if id == _Len {
   179  				mode = value
   180  			}
   181  
   182  		case *_Sum:
   183  			if t.is(func(t Type) bool {
   184  				switch t := under(t).(type) {
   185  				case *Basic:
   186  					if isString(t) && id == _Len {
   187  						return true
   188  					}
   189  				case *Array, *Slice, *Chan:
   190  					return true
   191  				case *Map:
   192  					if id == _Len {
   193  						return true
   194  					}
   195  				}
   196  				return false
   197  			}) {
   198  				mode = value
   199  			}
   200  		}
   201  
   202  		if mode == invalid && typ != Typ[Invalid] {
   203  			code := _InvalidCap
   204  			if id == _Len {
   205  				code = _InvalidLen
   206  			}
   207  			check.invalidArg(x, code, "%s for %s", x, bin.name)
   208  			return
   209  		}
   210  
   211  		x.mode = mode
   212  		x.typ = Typ[Int]
   213  		x.val = val
   214  		if check.Types != nil && mode != constant_ {
   215  			check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
   216  		}
   217  
   218  	case _Close:
   219  		// close(c)
   220  		c := asChan(x.typ)
   221  		if c == nil {
   222  			check.invalidArg(x, _InvalidClose, "%s is not a channel", x)
   223  			return
   224  		}
   225  		if c.dir == RecvOnly {
   226  			check.invalidArg(x, _InvalidClose, "%s must not be a receive-only channel", x)
   227  			return
   228  		}
   229  
   230  		x.mode = novalue
   231  		if check.Types != nil {
   232  			check.recordBuiltinType(call.Fun, makeSig(nil, c))
   233  		}
   234  
   235  	case _Complex:
   236  		// complex(x, y floatT) complexT
   237  		var y operand
   238  		arg(&y, 1)
   239  		if y.mode == invalid {
   240  			return
   241  		}
   242  
   243  		// convert or check untyped arguments
   244  		d := 0
   245  		if isUntyped(x.typ) {
   246  			d |= 1
   247  		}
   248  		if isUntyped(y.typ) {
   249  			d |= 2
   250  		}
   251  		switch d {
   252  		case 0:
   253  			// x and y are typed => nothing to do
   254  		case 1:
   255  			// only x is untyped => convert to type of y
   256  			check.convertUntyped(x, y.typ)
   257  		case 2:
   258  			// only y is untyped => convert to type of x
   259  			check.convertUntyped(&y, x.typ)
   260  		case 3:
   261  			// x and y are untyped =>
   262  			// 1) if both are constants, convert them to untyped
   263  			//    floating-point numbers if possible,
   264  			// 2) if one of them is not constant (possible because
   265  			//    it contains a shift that is yet untyped), convert
   266  			//    both of them to float64 since they must have the
   267  			//    same type to succeed (this will result in an error
   268  			//    because shifts of floats are not permitted)
   269  			if x.mode == constant_ && y.mode == constant_ {
   270  				toFloat := func(x *operand) {
   271  					if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
   272  						x.typ = Typ[UntypedFloat]
   273  					}
   274  				}
   275  				toFloat(x)
   276  				toFloat(&y)
   277  			} else {
   278  				check.convertUntyped(x, Typ[Float64])
   279  				check.convertUntyped(&y, Typ[Float64])
   280  				// x and y should be invalid now, but be conservative
   281  				// and check below
   282  			}
   283  		}
   284  		if x.mode == invalid || y.mode == invalid {
   285  			return
   286  		}
   287  
   288  		// both argument types must be identical
   289  		if !check.identical(x.typ, y.typ) {
   290  			check.invalidArg(x, _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ)
   291  			return
   292  		}
   293  
   294  		// the argument types must be of floating-point type
   295  		f := func(x Type) Type {
   296  			if t := asBasic(x); t != nil {
   297  				switch t.kind {
   298  				case Float32:
   299  					return Typ[Complex64]
   300  				case Float64:
   301  					return Typ[Complex128]
   302  				case UntypedFloat:
   303  					return Typ[UntypedComplex]
   304  				}
   305  			}
   306  			return nil
   307  		}
   308  		resTyp := check.applyTypeFunc(f, x.typ)
   309  		if resTyp == nil {
   310  			check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ)
   311  			return
   312  		}
   313  
   314  		// if both arguments are constants, the result is a constant
   315  		if x.mode == constant_ && y.mode == constant_ {
   316  			x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
   317  		} else {
   318  			x.mode = value
   319  		}
   320  
   321  		if check.Types != nil && x.mode != constant_ {
   322  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
   323  		}
   324  
   325  		x.typ = resTyp
   326  
   327  	case _Copy:
   328  		// copy(x, y []T) int
   329  		var dst Type
   330  		if t := asSlice(x.typ); t != nil {
   331  			dst = t.elem
   332  		}
   333  
   334  		var y operand
   335  		arg(&y, 1)
   336  		if y.mode == invalid {
   337  			return
   338  		}
   339  		var src Type
   340  		switch t := optype(y.typ).(type) {
   341  		case *Basic:
   342  			if isString(y.typ) {
   343  				src = universeByte
   344  			}
   345  		case *Slice:
   346  			src = t.elem
   347  		}
   348  
   349  		if dst == nil || src == nil {
   350  			check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y)
   351  			return
   352  		}
   353  
   354  		if !check.identical(dst, src) {
   355  			check.invalidArg(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
   356  			return
   357  		}
   358  
   359  		if check.Types != nil {
   360  			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
   361  		}
   362  		x.mode = value
   363  		x.typ = Typ[Int]
   364  
   365  	case _Delete:
   366  		// delete(m, k)
   367  		m := asMap(x.typ)
   368  		if m == nil {
   369  			check.invalidArg(x, _InvalidDelete, "%s is not a map", x)
   370  			return
   371  		}
   372  		arg(x, 1) // k
   373  		if x.mode == invalid {
   374  			return
   375  		}
   376  
   377  		check.assignment(x, m.key, "argument to delete")
   378  		if x.mode == invalid {
   379  			return
   380  		}
   381  
   382  		x.mode = novalue
   383  		if check.Types != nil {
   384  			check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key))
   385  		}
   386  
   387  	case _Imag, _Real:
   388  		// imag(complexT) floatT
   389  		// real(complexT) floatT
   390  
   391  		// convert or check untyped argument
   392  		if isUntyped(x.typ) {
   393  			if x.mode == constant_ {
   394  				// an untyped constant number can always be considered
   395  				// as a complex constant
   396  				if isNumeric(x.typ) {
   397  					x.typ = Typ[UntypedComplex]
   398  				}
   399  			} else {
   400  				// an untyped non-constant argument may appear if
   401  				// it contains a (yet untyped non-constant) shift
   402  				// expression: convert it to complex128 which will
   403  				// result in an error (shift of complex value)
   404  				check.convertUntyped(x, Typ[Complex128])
   405  				// x should be invalid now, but be conservative and check
   406  				if x.mode == invalid {
   407  					return
   408  				}
   409  			}
   410  		}
   411  
   412  		// the argument must be of complex type
   413  		f := func(x Type) Type {
   414  			if t := asBasic(x); t != nil {
   415  				switch t.kind {
   416  				case Complex64:
   417  					return Typ[Float32]
   418  				case Complex128:
   419  					return Typ[Float64]
   420  				case UntypedComplex:
   421  					return Typ[UntypedFloat]
   422  				}
   423  			}
   424  			return nil
   425  		}
   426  		resTyp := check.applyTypeFunc(f, x.typ)
   427  		if resTyp == nil {
   428  			code := _InvalidImag
   429  			if id == _Real {
   430  				code = _InvalidReal
   431  			}
   432  			check.invalidArg(x, code, "argument has type %s, expected complex type", x.typ)
   433  			return
   434  		}
   435  
   436  		// if the argument is a constant, the result is a constant
   437  		if x.mode == constant_ {
   438  			if id == _Real {
   439  				x.val = constant.Real(x.val)
   440  			} else {
   441  				x.val = constant.Imag(x.val)
   442  			}
   443  		} else {
   444  			x.mode = value
   445  		}
   446  
   447  		if check.Types != nil && x.mode != constant_ {
   448  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
   449  		}
   450  
   451  		x.typ = resTyp
   452  
   453  	case _Make:
   454  		// make(T, n)
   455  		// make(T, n, m)
   456  		// (no argument evaluated yet)
   457  		arg0 := call.Args[0]
   458  		T := check.varType(arg0)
   459  		if T == Typ[Invalid] {
   460  			return
   461  		}
   462  
   463  		min, max := -1, 10
   464  		var valid func(t Type) bool
   465  		valid = func(t Type) bool {
   466  			var m int
   467  			switch t := optype(t).(type) {
   468  			case *Slice:
   469  				m = 2
   470  			case *Map, *Chan:
   471  				m = 1
   472  			case *_Sum:
   473  				return t.is(valid)
   474  			default:
   475  				return false
   476  			}
   477  			if m > min {
   478  				min = m
   479  			}
   480  			if m+1 < max {
   481  				max = m + 1
   482  			}
   483  			return true
   484  		}
   485  
   486  		if !valid(T) {
   487  			check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)
   488  			return
   489  		}
   490  		if nargs < min || max < nargs {
   491  			if min == max {
   492  				check.errorf(call, _WrongArgCount, "%v expects %d arguments; found %d", call, min, nargs)
   493  			} else {
   494  				check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, max, nargs)
   495  			}
   496  			return
   497  		}
   498  
   499  		types := []Type{T}
   500  		var sizes []int64 // constant integer arguments, if any
   501  		for _, arg := range call.Args[1:] {
   502  			typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
   503  			types = append(types, typ)
   504  			if size >= 0 {
   505  				sizes = append(sizes, size)
   506  			}
   507  		}
   508  		if len(sizes) == 2 && sizes[0] > sizes[1] {
   509  			check.invalidArg(call.Args[1], _SwappedMakeArgs, "length and capacity swapped")
   510  			// safe to continue
   511  		}
   512  		x.mode = value
   513  		x.typ = T
   514  		if check.Types != nil {
   515  			check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
   516  		}
   517  
   518  	case _New:
   519  		// new(T)
   520  		// (no argument evaluated yet)
   521  		T := check.varType(call.Args[0])
   522  		if T == Typ[Invalid] {
   523  			return
   524  		}
   525  
   526  		x.mode = value
   527  		x.typ = &Pointer{base: T}
   528  		if check.Types != nil {
   529  			check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
   530  		}
   531  
   532  	case _Panic:
   533  		// panic(x)
   534  		// record panic call if inside a function with result parameters
   535  		// (for use in Checker.isTerminating)
   536  		if check.sig != nil && check.sig.results.Len() > 0 {
   537  			// function has result parameters
   538  			p := check.isPanic
   539  			if p == nil {
   540  				// allocate lazily
   541  				p = make(map[*ast.CallExpr]bool)
   542  				check.isPanic = p
   543  			}
   544  			p[call] = true
   545  		}
   546  
   547  		check.assignment(x, &emptyInterface, "argument to panic")
   548  		if x.mode == invalid {
   549  			return
   550  		}
   551  
   552  		x.mode = novalue
   553  		if check.Types != nil {
   554  			check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
   555  		}
   556  
   557  	case _Print, _Println:
   558  		// print(x, y, ...)
   559  		// println(x, y, ...)
   560  		var params []Type
   561  		if nargs > 0 {
   562  			params = make([]Type, nargs)
   563  			for i := 0; i < nargs; i++ {
   564  				if i > 0 {
   565  					arg(x, i) // first argument already evaluated
   566  				}
   567  				check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name)
   568  				if x.mode == invalid {
   569  					// TODO(gri) "use" all arguments?
   570  					return
   571  				}
   572  				params[i] = x.typ
   573  			}
   574  		}
   575  
   576  		x.mode = novalue
   577  		if check.Types != nil {
   578  			check.recordBuiltinType(call.Fun, makeSig(nil, params...))
   579  		}
   580  
   581  	case _Recover:
   582  		// recover() interface{}
   583  		x.mode = value
   584  		x.typ = &emptyInterface
   585  		if check.Types != nil {
   586  			check.recordBuiltinType(call.Fun, makeSig(x.typ))
   587  		}
   588  
   589  	case _Add:
   590  		// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
   591  		if !check.allowVersion(check.pkg, 1, 17) {
   592  			check.errorf(call.Fun, _InvalidUnsafeAdd, "unsafe.Add requires go1.17 or later")
   593  			return
   594  		}
   595  
   596  		check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
   597  		if x.mode == invalid {
   598  			return
   599  		}
   600  
   601  		var y operand
   602  		arg(&y, 1)
   603  		if !check.isValidIndex(&y, _InvalidUnsafeAdd, "length", true) {
   604  			return
   605  		}
   606  
   607  		x.mode = value
   608  		x.typ = Typ[UnsafePointer]
   609  		if check.Types != nil {
   610  			check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
   611  		}
   612  
   613  	case _Alignof:
   614  		// unsafe.Alignof(x T) uintptr
   615  		if asTypeParam(x.typ) != nil {
   616  			check.invalidOp(call, _Todo, "unsafe.Alignof undefined for %s", x)
   617  			return
   618  		}
   619  		check.assignment(x, nil, "argument to unsafe.Alignof")
   620  		if x.mode == invalid {
   621  			return
   622  		}
   623  
   624  		x.mode = constant_
   625  		x.val = constant.MakeInt64(check.conf.alignof(x.typ))
   626  		x.typ = Typ[Uintptr]
   627  		// result is constant - no need to record signature
   628  
   629  	case _Offsetof:
   630  		// unsafe.Offsetof(x T) uintptr, where x must be a selector
   631  		// (no argument evaluated yet)
   632  		arg0 := call.Args[0]
   633  		selx, _ := unparen(arg0).(*ast.SelectorExpr)
   634  		if selx == nil {
   635  			check.invalidArg(arg0, _BadOffsetofSyntax, "%s is not a selector expression", arg0)
   636  			check.use(arg0)
   637  			return
   638  		}
   639  
   640  		check.expr(x, selx.X)
   641  		if x.mode == invalid {
   642  			return
   643  		}
   644  
   645  		base := derefStructPtr(x.typ)
   646  		sel := selx.Sel.Name
   647  		obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel)
   648  		switch obj.(type) {
   649  		case nil:
   650  			check.invalidArg(x, _MissingFieldOrMethod, "%s has no single field %s", base, sel)
   651  			return
   652  		case *Func:
   653  			// TODO(gri) Using derefStructPtr may result in methods being found
   654  			// that don't actually exist. An error either way, but the error
   655  			// message is confusing. See: https://play.golang.org/p/al75v23kUy ,
   656  			// but go/types reports: "invalid argument: x.m is a method value".
   657  			check.invalidArg(arg0, _InvalidOffsetof, "%s is a method value", arg0)
   658  			return
   659  		}
   660  		if indirect {
   661  			check.invalidArg(x, _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base)
   662  			return
   663  		}
   664  
   665  		// TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)?
   666  		check.recordSelection(selx, FieldVal, base, obj, index, false)
   667  
   668  		offs := check.conf.offsetof(base, index)
   669  		x.mode = constant_
   670  		x.val = constant.MakeInt64(offs)
   671  		x.typ = Typ[Uintptr]
   672  		// result is constant - no need to record signature
   673  
   674  	case _Sizeof:
   675  		// unsafe.Sizeof(x T) uintptr
   676  		if asTypeParam(x.typ) != nil {
   677  			check.invalidOp(call, _Todo, "unsafe.Sizeof undefined for %s", x)
   678  			return
   679  		}
   680  		check.assignment(x, nil, "argument to unsafe.Sizeof")
   681  		if x.mode == invalid {
   682  			return
   683  		}
   684  
   685  		x.mode = constant_
   686  		x.val = constant.MakeInt64(check.conf.sizeof(x.typ))
   687  		x.typ = Typ[Uintptr]
   688  		// result is constant - no need to record signature
   689  
   690  	case _Slice:
   691  		// unsafe.Slice(ptr *T, len IntegerType) []T
   692  		if !check.allowVersion(check.pkg, 1, 17) {
   693  			check.errorf(call.Fun, _InvalidUnsafeSlice, "unsafe.Slice requires go1.17 or later")
   694  			return
   695  		}
   696  
   697  		typ := asPointer(x.typ)
   698  		if typ == nil {
   699  			check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x)
   700  			return
   701  		}
   702  
   703  		var y operand
   704  		arg(&y, 1)
   705  		if !check.isValidIndex(&y, _InvalidUnsafeSlice, "length", false) {
   706  			return
   707  		}
   708  
   709  		x.mode = value
   710  		x.typ = NewSlice(typ.base)
   711  		if check.Types != nil {
   712  			check.recordBuiltinType(call.Fun, makeSig(x.typ, typ, y.typ))
   713  		}
   714  
   715  	case _Assert:
   716  		// assert(pred) causes a typechecker error if pred is false.
   717  		// The result of assert is the value of pred if there is no error.
   718  		// Note: assert is only available in self-test mode.
   719  		if x.mode != constant_ || !isBoolean(x.typ) {
   720  			check.invalidArg(x, _Test, "%s is not a boolean constant", x)
   721  			return
   722  		}
   723  		if x.val.Kind() != constant.Bool {
   724  			check.errorf(x, _Test, "internal error: value of %s should be a boolean constant", x)
   725  			return
   726  		}
   727  		if !constant.BoolVal(x.val) {
   728  			check.errorf(call, _Test, "%v failed", call)
   729  			// compile-time assertion failure - safe to continue
   730  		}
   731  		// result is constant - no need to record signature
   732  
   733  	case _Trace:
   734  		// trace(x, y, z, ...) dumps the positions, expressions, and
   735  		// values of its arguments. The result of trace is the value
   736  		// of the first argument.
   737  		// Note: trace is only available in self-test mode.
   738  		// (no argument evaluated yet)
   739  		if nargs == 0 {
   740  			check.dump("%v: trace() without arguments", call.Pos())
   741  			x.mode = novalue
   742  			break
   743  		}
   744  		var t operand
   745  		x1 := x
   746  		for _, arg := range call.Args {
   747  			check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
   748  			check.dump("%v: %s", x1.Pos(), x1)
   749  			x1 = &t // use incoming x only for first argument
   750  		}
   751  		// trace is only available in test mode - no need to record signature
   752  
   753  	default:
   754  		unreachable()
   755  	}
   756  
   757  	return true
   758  }
   759  
   760  // applyTypeFunc applies f to x. If x is a type parameter,
   761  // the result is a type parameter constrained by an new
   762  // interface bound. The type bounds for that interface
   763  // are computed by applying f to each of the type bounds
   764  // of x. If any of these applications of f return nil,
   765  // applyTypeFunc returns nil.
   766  // If x is not a type parameter, the result is f(x).
   767  func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
   768  	if tp := asTypeParam(x); tp != nil {
   769  		// Test if t satisfies the requirements for the argument
   770  		// type and collect possible result types at the same time.
   771  		var rtypes []Type
   772  		if !tp.Bound().is(func(x Type) bool {
   773  			if r := f(x); r != nil {
   774  				rtypes = append(rtypes, r)
   775  				return true
   776  			}
   777  			return false
   778  		}) {
   779  			return nil
   780  		}
   781  
   782  		// construct a suitable new type parameter
   783  		tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "<type parameter>", nil)
   784  		ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
   785  		tsum := _NewSum(rtypes)
   786  		ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum}
   787  
   788  		return ptyp
   789  	}
   790  
   791  	return f(x)
   792  }
   793  
   794  // makeSig makes a signature for the given argument and result types.
   795  // Default types are used for untyped arguments, and res may be nil.
   796  func makeSig(res Type, args ...Type) *Signature {
   797  	list := make([]*Var, len(args))
   798  	for i, param := range args {
   799  		list[i] = NewVar(token.NoPos, nil, "", Default(param))
   800  	}
   801  	params := NewTuple(list...)
   802  	var result *Tuple
   803  	if res != nil {
   804  		assert(!isUntyped(res))
   805  		result = NewTuple(NewVar(token.NoPos, nil, "", res))
   806  	}
   807  	return &Signature{params: params, results: result}
   808  }
   809  
   810  // implicitArrayDeref returns A if typ is of the form *A and A is an array;
   811  // otherwise it returns typ.
   812  //
   813  func implicitArrayDeref(typ Type) Type {
   814  	if p, ok := typ.(*Pointer); ok {
   815  		if a := asArray(p.base); a != nil {
   816  			return a
   817  		}
   818  	}
   819  	return typ
   820  }
   821  
   822  // unparen returns e with any enclosing parentheses stripped.
   823  func unparen(e ast.Expr) ast.Expr {
   824  	for {
   825  		p, ok := e.(*ast.ParenExpr)
   826  		if !ok {
   827  			return e
   828  		}
   829  		e = p.X
   830  	}
   831  }
   832  

View as plain text