...

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

View as plain text