Source file src/go/types/builtins.go

     1  // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
     2  // Source: ../../cmd/compile/internal/types2/builtins.go
     3  
     4  // Copyright 2012 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  // This file implements typechecking of builtin function calls.
     9  
    10  package types
    11  
    12  import (
    13  	"go/ast"
    14  	"go/constant"
    15  	"go/token"
    16  	. "internal/types/errors"
    17  )
    18  
    19  // builtin type-checks a call to the built-in specified by id and
    20  // reports whether the call is valid, with *x holding the result;
    21  // but x.expr is not set. If the call is invalid, the result is
    22  // false, and *x is undefined.
    23  func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
    24  	argList := call.Args
    25  
    26  	// append is the only built-in that permits the use of ... for the last argument
    27  	bin := predeclaredFuncs[id]
    28  	if hasDots(call) && id != _Append {
    29  		check.errorf(dddErrPos(call),
    30  			InvalidDotDotDot,
    31  			invalidOp+"invalid use of ... with built-in %s", bin.name)
    32  		check.use(argList...)
    33  		return
    34  	}
    35  
    36  	// For len(x) and cap(x) we need to know if x contains any function calls or
    37  	// receive operations. Save/restore current setting and set hasCallOrRecv to
    38  	// false for the evaluation of x so that we can check it afterwards.
    39  	// Note: We must do this _before_ calling exprList because exprList evaluates
    40  	//       all arguments.
    41  	if id == _Len || id == _Cap {
    42  		defer func(b bool) {
    43  			check.hasCallOrRecv = b
    44  		}(check.hasCallOrRecv)
    45  		check.hasCallOrRecv = false
    46  	}
    47  
    48  	// Evaluate arguments for built-ins that use ordinary (value) arguments.
    49  	// For built-ins with special argument handling (make, new, etc.),
    50  	// evaluation is done by the respective built-in code.
    51  	var args []*operand // not valid for _Make, _New, _Offsetof, _Trace
    52  	var nargs int
    53  	switch id {
    54  	default:
    55  		// check all arguments
    56  		args = check.exprList(argList)
    57  		nargs = len(args)
    58  		for _, a := range args {
    59  			if a.mode == invalid {
    60  				return
    61  			}
    62  		}
    63  		// first argument is always in x
    64  		if nargs > 0 {
    65  			*x = *args[0]
    66  		}
    67  	case _Make, _New, _Offsetof, _Trace:
    68  		// arguments require special handling
    69  		nargs = len(argList)
    70  	}
    71  
    72  	// check argument count
    73  	{
    74  		msg := ""
    75  		if nargs < bin.nargs {
    76  			msg = "not enough"
    77  		} else if !bin.variadic && nargs > bin.nargs {
    78  			msg = "too many"
    79  		}
    80  		if msg != "" {
    81  			check.errorf(argErrPos(call), WrongArgCount, invalidOp+"%s arguments for %v (expected %d, found %d)", msg, call, bin.nargs, nargs)
    82  			return
    83  		}
    84  	}
    85  
    86  	switch id {
    87  	case _Append:
    88  		// append(s S, x ...E) S, where E is the element type of S
    89  		// spec: "The variadic function append appends zero or more values x to
    90  		// a slice s of type S and returns the resulting slice, also of type S.
    91  		// The values x are passed to a parameter of type ...E where E is the
    92  		// element type of S and the respective parameter passing rules apply.
    93  		// As a special case, append also accepts a first argument assignable
    94  		// to type []byte with a second argument of string type followed by ... .
    95  		// This form appends the bytes of the string."
    96  
    97  		// get special case out of the way
    98  		var sig *Signature
    99  		if nargs == 2 && hasDots(call) {
   100  			if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
   101  				y := args[1]
   102  				typeset(y.typ, func(_, u Type) bool {
   103  					if s, _ := u.(*Slice); s != nil && Identical(s.elem, universeByte) {
   104  						return true
   105  					}
   106  					if isString(u) {
   107  						return true
   108  					}
   109  					y = nil
   110  					return false
   111  				})
   112  				if y != nil {
   113  					// setting the signature also signals that we're done
   114  					sig = makeSig(x.typ, x.typ, y.typ)
   115  					sig.variadic = true
   116  				}
   117  			}
   118  		}
   119  
   120  		// general case
   121  		if sig == nil {
   122  			// spec: "If S is a type parameter, all types in its type set
   123  			// must have the same underlying slice type []E."
   124  			E, err := sliceElem(x)
   125  			if err != nil {
   126  				check.errorf(x, InvalidAppend, "invalid append: %s", err.format(check))
   127  				return
   128  			}
   129  			// check arguments by creating custom signature
   130  			sig = makeSig(x.typ, x.typ, NewSlice(E)) // []E required for variadic signature
   131  			sig.variadic = true
   132  			check.arguments(call, sig, nil, nil, args, nil) // discard result (we know the result type)
   133  			// ok to continue even if check.arguments reported errors
   134  		}
   135  
   136  		if check.recordTypes() {
   137  			check.recordBuiltinType(call.Fun, sig)
   138  		}
   139  		x.mode = value
   140  		// x.typ is unchanged
   141  
   142  	case _Cap, _Len:
   143  		// cap(x)
   144  		// len(x)
   145  		mode := invalid
   146  		var val constant.Value
   147  		switch t := arrayPtrDeref(under(x.typ)).(type) {
   148  		case *Basic:
   149  			if isString(t) && id == _Len {
   150  				if x.mode == constant_ {
   151  					mode = constant_
   152  					val = constant.MakeInt64(int64(len(constant.StringVal(x.val))))
   153  				} else {
   154  					mode = value
   155  				}
   156  			}
   157  
   158  		case *Array:
   159  			mode = value
   160  			// spec: "The expressions len(s) and cap(s) are constants
   161  			// if the type of s is an array or pointer to an array and
   162  			// the expression s does not contain channel receives or
   163  			// function calls; in this case s is not evaluated."
   164  			if !check.hasCallOrRecv {
   165  				mode = constant_
   166  				if t.len >= 0 {
   167  					val = constant.MakeInt64(t.len)
   168  				} else {
   169  					val = constant.MakeUnknown()
   170  				}
   171  			}
   172  
   173  		case *Slice, *Chan:
   174  			mode = value
   175  
   176  		case *Map:
   177  			if id == _Len {
   178  				mode = value
   179  			}
   180  
   181  		case *Interface:
   182  			if !isTypeParam(x.typ) {
   183  				break
   184  			}
   185  			if underIs(x.typ, func(u Type) bool {
   186  				switch t := arrayPtrDeref(u).(type) {
   187  				case *Basic:
   188  					if isString(t) && id == _Len {
   189  						return true
   190  					}
   191  				case *Array, *Slice, *Chan:
   192  					return true
   193  				case *Map:
   194  					if id == _Len {
   195  						return true
   196  					}
   197  				}
   198  				return false
   199  			}) {
   200  				mode = value
   201  			}
   202  		}
   203  
   204  		if mode == invalid {
   205  			// avoid error if underlying type is invalid
   206  			if isValid(under(x.typ)) {
   207  				code := InvalidCap
   208  				if id == _Len {
   209  					code = InvalidLen
   210  				}
   211  				check.errorf(x, code, invalidArg+"%s for built-in %s", x, bin.name)
   212  			}
   213  			return
   214  		}
   215  
   216  		// record the signature before changing x.typ
   217  		if check.recordTypes() && mode != constant_ {
   218  			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
   219  		}
   220  
   221  		x.mode = mode
   222  		x.typ = Typ[Int]
   223  		x.val = val
   224  
   225  	case _Clear:
   226  		// clear(m)
   227  		check.verifyVersionf(call.Fun, go1_21, "clear")
   228  
   229  		if !underIs(x.typ, func(u Type) bool {
   230  			switch u.(type) {
   231  			case *Map, *Slice:
   232  				return true
   233  			}
   234  			check.errorf(x, InvalidClear, invalidArg+"cannot clear %s: argument must be (or constrained by) map or slice", x)
   235  			return false
   236  		}) {
   237  			return
   238  		}
   239  
   240  		x.mode = novalue
   241  		if check.recordTypes() {
   242  			check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
   243  		}
   244  
   245  	case _Close:
   246  		// close(c)
   247  		if !underIs(x.typ, func(u Type) bool {
   248  			uch, _ := u.(*Chan)
   249  			if uch == nil {
   250  				check.errorf(x, InvalidClose, invalidOp+"cannot close non-channel %s", x)
   251  				return false
   252  			}
   253  			if uch.dir == RecvOnly {
   254  				check.errorf(x, InvalidClose, invalidOp+"cannot close receive-only channel %s", x)
   255  				return false
   256  			}
   257  			return true
   258  		}) {
   259  			return
   260  		}
   261  		x.mode = novalue
   262  		if check.recordTypes() {
   263  			check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
   264  		}
   265  
   266  	case _Complex:
   267  		// complex(x, y floatT) complexT
   268  		y := args[1]
   269  
   270  		// convert or check untyped arguments
   271  		d := 0
   272  		if isUntyped(x.typ) {
   273  			d |= 1
   274  		}
   275  		if isUntyped(y.typ) {
   276  			d |= 2
   277  		}
   278  		switch d {
   279  		case 0:
   280  			// x and y are typed => nothing to do
   281  		case 1:
   282  			// only x is untyped => convert to type of y
   283  			check.convertUntyped(x, y.typ)
   284  		case 2:
   285  			// only y is untyped => convert to type of x
   286  			check.convertUntyped(y, x.typ)
   287  		case 3:
   288  			// x and y are untyped =>
   289  			// 1) if both are constants, convert them to untyped
   290  			//    floating-point numbers if possible,
   291  			// 2) if one of them is not constant (possible because
   292  			//    it contains a shift that is yet untyped), convert
   293  			//    both of them to float64 since they must have the
   294  			//    same type to succeed (this will result in an error
   295  			//    because shifts of floats are not permitted)
   296  			if x.mode == constant_ && y.mode == constant_ {
   297  				toFloat := func(x *operand) {
   298  					if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
   299  						x.typ = Typ[UntypedFloat]
   300  					}
   301  				}
   302  				toFloat(x)
   303  				toFloat(y)
   304  			} else {
   305  				check.convertUntyped(x, Typ[Float64])
   306  				check.convertUntyped(y, Typ[Float64])
   307  				// x and y should be invalid now, but be conservative
   308  				// and check below
   309  			}
   310  		}
   311  		if x.mode == invalid || y.mode == invalid {
   312  			return
   313  		}
   314  
   315  		// both argument types must be identical
   316  		if !Identical(x.typ, y.typ) {
   317  			check.errorf(x, InvalidComplex, invalidOp+"%v (mismatched types %s and %s)", call, x.typ, y.typ)
   318  			return
   319  		}
   320  
   321  		// the argument types must be of floating-point type
   322  		// (applyTypeFunc never calls f with a type parameter)
   323  		f := func(typ Type) Type {
   324  			assert(!isTypeParam(typ))
   325  			if t, _ := under(typ).(*Basic); t != nil {
   326  				switch t.kind {
   327  				case Float32:
   328  					return Typ[Complex64]
   329  				case Float64:
   330  					return Typ[Complex128]
   331  				case UntypedFloat:
   332  					return Typ[UntypedComplex]
   333  				}
   334  			}
   335  			return nil
   336  		}
   337  		resTyp := check.applyTypeFunc(f, x, id)
   338  		if resTyp == nil {
   339  			check.errorf(x, InvalidComplex, invalidArg+"arguments have type %s, expected floating-point", x.typ)
   340  			return
   341  		}
   342  
   343  		// if both arguments are constants, the result is a constant
   344  		if x.mode == constant_ && y.mode == constant_ {
   345  			x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
   346  		} else {
   347  			x.mode = value
   348  		}
   349  
   350  		if check.recordTypes() && x.mode != constant_ {
   351  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
   352  		}
   353  
   354  		x.typ = resTyp
   355  
   356  	case _Copy:
   357  		// copy(x, y []E) int
   358  		// spec: "The function copy copies slice elements from a source src to a destination
   359  		// dst and returns the number of elements copied. Both arguments must have identical
   360  		// element type E and must be assignable to a slice of type []E.
   361  		// The number of elements copied is the minimum of len(src) and len(dst).
   362  		// As a special case, copy also accepts a destination argument assignable to type
   363  		// []byte with a source argument of a string type.
   364  		// This form copies the bytes from the string into the byte slice."
   365  
   366  		// get special case out of the way
   367  		y := args[1]
   368  		var special bool
   369  		if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
   370  			special = true
   371  			typeset(y.typ, func(_, u Type) bool {
   372  				if s, _ := u.(*Slice); s != nil && Identical(s.elem, universeByte) {
   373  					return true
   374  				}
   375  				if isString(u) {
   376  					return true
   377  				}
   378  				special = false
   379  				return false
   380  			})
   381  		}
   382  
   383  		// general case
   384  		if !special {
   385  			// spec: "If the type of one or both arguments is a type parameter, all types
   386  			// in their respective type sets must have the same underlying slice type []E."
   387  			dstE, err := sliceElem(x)
   388  			if err != nil {
   389  				check.errorf(x, InvalidCopy, "invalid copy: %s", err.format(check))
   390  				return
   391  			}
   392  			srcE, err := sliceElem(y)
   393  			if err != nil {
   394  				// If we have a string, for a better error message proceed with byte element type.
   395  				if !allString(y.typ) {
   396  					check.errorf(y, InvalidCopy, "invalid copy: %s", err.format(check))
   397  					return
   398  				}
   399  				srcE = universeByte
   400  			}
   401  			if !Identical(dstE, srcE) {
   402  				check.errorf(x, InvalidCopy, "invalid copy: arguments %s and %s have different element types %s and %s", x, y, dstE, srcE)
   403  				return
   404  			}
   405  		}
   406  
   407  		if check.recordTypes() {
   408  			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
   409  		}
   410  		x.mode = value
   411  		x.typ = Typ[Int]
   412  
   413  	case _Delete:
   414  		// delete(map_, key)
   415  		// map_ must be a map type or a type parameter describing map types.
   416  		// The key cannot be a type parameter for now.
   417  		map_ := x.typ
   418  		var key Type
   419  		if !underIs(map_, func(u Type) bool {
   420  			map_, _ := u.(*Map)
   421  			if map_ == nil {
   422  				check.errorf(x, InvalidDelete, invalidArg+"%s is not a map", x)
   423  				return false
   424  			}
   425  			if key != nil && !Identical(map_.key, key) {
   426  				check.errorf(x, InvalidDelete, invalidArg+"maps of %s must have identical key types", x)
   427  				return false
   428  			}
   429  			key = map_.key
   430  			return true
   431  		}) {
   432  			return
   433  		}
   434  
   435  		*x = *args[1] // key
   436  		check.assignment(x, key, "argument to delete")
   437  		if x.mode == invalid {
   438  			return
   439  		}
   440  
   441  		x.mode = novalue
   442  		if check.recordTypes() {
   443  			check.recordBuiltinType(call.Fun, makeSig(nil, map_, key))
   444  		}
   445  
   446  	case _Imag, _Real:
   447  		// imag(complexT) floatT
   448  		// real(complexT) floatT
   449  
   450  		// convert or check untyped argument
   451  		if isUntyped(x.typ) {
   452  			if x.mode == constant_ {
   453  				// an untyped constant number can always be considered
   454  				// as a complex constant
   455  				if isNumeric(x.typ) {
   456  					x.typ = Typ[UntypedComplex]
   457  				}
   458  			} else {
   459  				// an untyped non-constant argument may appear if
   460  				// it contains a (yet untyped non-constant) shift
   461  				// expression: convert it to complex128 which will
   462  				// result in an error (shift of complex value)
   463  				check.convertUntyped(x, Typ[Complex128])
   464  				// x should be invalid now, but be conservative and check
   465  				if x.mode == invalid {
   466  					return
   467  				}
   468  			}
   469  		}
   470  
   471  		// the argument must be of complex type
   472  		// (applyTypeFunc never calls f with a type parameter)
   473  		f := func(typ Type) Type {
   474  			assert(!isTypeParam(typ))
   475  			if t, _ := under(typ).(*Basic); t != nil {
   476  				switch t.kind {
   477  				case Complex64:
   478  					return Typ[Float32]
   479  				case Complex128:
   480  					return Typ[Float64]
   481  				case UntypedComplex:
   482  					return Typ[UntypedFloat]
   483  				}
   484  			}
   485  			return nil
   486  		}
   487  		resTyp := check.applyTypeFunc(f, x, id)
   488  		if resTyp == nil {
   489  			code := InvalidImag
   490  			if id == _Real {
   491  				code = InvalidReal
   492  			}
   493  			check.errorf(x, code, invalidArg+"argument has type %s, expected complex type", x.typ)
   494  			return
   495  		}
   496  
   497  		// if the argument is a constant, the result is a constant
   498  		if x.mode == constant_ {
   499  			if id == _Real {
   500  				x.val = constant.Real(x.val)
   501  			} else {
   502  				x.val = constant.Imag(x.val)
   503  			}
   504  		} else {
   505  			x.mode = value
   506  		}
   507  
   508  		if check.recordTypes() && x.mode != constant_ {
   509  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
   510  		}
   511  
   512  		x.typ = resTyp
   513  
   514  	case _Make:
   515  		// make(T, n)
   516  		// make(T, n, m)
   517  		// (no argument evaluated yet)
   518  		arg0 := argList[0]
   519  		T := check.varType(arg0)
   520  		if !isValid(T) {
   521  			return
   522  		}
   523  
   524  		u, err := commonUnder(T, func(_, u Type) *typeError {
   525  			switch u.(type) {
   526  			case *Slice, *Map, *Chan:
   527  				return nil // ok
   528  			case nil:
   529  				return typeErrorf("no specific type")
   530  			default:
   531  				return typeErrorf("type must be slice, map, or channel")
   532  			}
   533  		})
   534  		if err != nil {
   535  			check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: %s", arg0, err.format(check))
   536  			return
   537  		}
   538  
   539  		var min int // minimum number of arguments
   540  		switch u.(type) {
   541  		case *Slice:
   542  			min = 2
   543  		case *Map, *Chan:
   544  			min = 1
   545  		default:
   546  			// any other type was excluded above
   547  			panic("unreachable")
   548  		}
   549  		if nargs < min || min+1 < nargs {
   550  			check.errorf(call, WrongArgCount, invalidOp+"%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
   551  			return
   552  		}
   553  
   554  		types := []Type{T}
   555  		var sizes []int64 // constant integer arguments, if any
   556  		for _, arg := range argList[1:] {
   557  			typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
   558  			types = append(types, typ)
   559  			if size >= 0 {
   560  				sizes = append(sizes, size)
   561  			}
   562  		}
   563  		if len(sizes) == 2 && sizes[0] > sizes[1] {
   564  			check.error(argList[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
   565  			// safe to continue
   566  		}
   567  		x.mode = value
   568  		x.typ = T
   569  		if check.recordTypes() {
   570  			check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
   571  		}
   572  
   573  	case _Max, _Min:
   574  		// max(x, ...)
   575  		// min(x, ...)
   576  		check.verifyVersionf(call.Fun, go1_21, "built-in %s", bin.name)
   577  
   578  		op := token.LSS
   579  		if id == _Max {
   580  			op = token.GTR
   581  		}
   582  
   583  		for i, a := range args {
   584  			if a.mode == invalid {
   585  				return
   586  			}
   587  
   588  			if !allOrdered(a.typ) {
   589  				check.errorf(a, InvalidMinMaxOperand, invalidArg+"%s cannot be ordered", a)
   590  				return
   591  			}
   592  
   593  			// The first argument is already in x and there's nothing left to do.
   594  			if i > 0 {
   595  				check.matchTypes(x, a)
   596  				if x.mode == invalid {
   597  					return
   598  				}
   599  
   600  				if !Identical(x.typ, a.typ) {
   601  					check.errorf(a, MismatchedTypes, invalidArg+"mismatched types %s (previous argument) and %s (type of %s)", x.typ, a.typ, a.expr)
   602  					return
   603  				}
   604  
   605  				if x.mode == constant_ && a.mode == constant_ {
   606  					if constant.Compare(a.val, op, x.val) {
   607  						*x = *a
   608  					}
   609  				} else {
   610  					x.mode = value
   611  				}
   612  			}
   613  		}
   614  
   615  		// If nargs == 1, make sure x.mode is either a value or a constant.
   616  		if x.mode != constant_ {
   617  			x.mode = value
   618  			// A value must not be untyped.
   619  			check.assignment(x, &emptyInterface, "argument to built-in "+bin.name)
   620  			if x.mode == invalid {
   621  				return
   622  			}
   623  		}
   624  
   625  		// Use the final type computed above for all arguments.
   626  		for _, a := range args {
   627  			check.updateExprType(a.expr, x.typ, true)
   628  		}
   629  
   630  		if check.recordTypes() && x.mode != constant_ {
   631  			types := make([]Type, nargs)
   632  			for i := range types {
   633  				types[i] = x.typ
   634  			}
   635  			check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
   636  		}
   637  
   638  	case _New:
   639  		// new(T)
   640  		// (no argument evaluated yet)
   641  		T := check.varType(argList[0])
   642  		if !isValid(T) {
   643  			return
   644  		}
   645  
   646  		x.mode = value
   647  		x.typ = &Pointer{base: T}
   648  		if check.recordTypes() {
   649  			check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
   650  		}
   651  
   652  	case _Panic:
   653  		// panic(x)
   654  		// record panic call if inside a function with result parameters
   655  		// (for use in Checker.isTerminating)
   656  		if check.sig != nil && check.sig.results.Len() > 0 {
   657  			// function has result parameters
   658  			p := check.isPanic
   659  			if p == nil {
   660  				// allocate lazily
   661  				p = make(map[*ast.CallExpr]bool)
   662  				check.isPanic = p
   663  			}
   664  			p[call] = true
   665  		}
   666  
   667  		check.assignment(x, &emptyInterface, "argument to panic")
   668  		if x.mode == invalid {
   669  			return
   670  		}
   671  
   672  		x.mode = novalue
   673  		if check.recordTypes() {
   674  			check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
   675  		}
   676  
   677  	case _Print, _Println:
   678  		// print(x, y, ...)
   679  		// println(x, y, ...)
   680  		var params []Type
   681  		if nargs > 0 {
   682  			params = make([]Type, nargs)
   683  			for i, a := range args {
   684  				check.assignment(a, nil, "argument to built-in "+predeclaredFuncs[id].name)
   685  				if a.mode == invalid {
   686  					return
   687  				}
   688  				params[i] = a.typ
   689  			}
   690  		}
   691  
   692  		x.mode = novalue
   693  		if check.recordTypes() {
   694  			check.recordBuiltinType(call.Fun, makeSig(nil, params...))
   695  		}
   696  
   697  	case _Recover:
   698  		// recover() interface{}
   699  		x.mode = value
   700  		x.typ = &emptyInterface
   701  		if check.recordTypes() {
   702  			check.recordBuiltinType(call.Fun, makeSig(x.typ))
   703  		}
   704  
   705  	case _Add:
   706  		// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
   707  		check.verifyVersionf(call.Fun, go1_17, "unsafe.Add")
   708  
   709  		check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
   710  		if x.mode == invalid {
   711  			return
   712  		}
   713  
   714  		y := args[1]
   715  		if !check.isValidIndex(y, InvalidUnsafeAdd, "length", true) {
   716  			return
   717  		}
   718  
   719  		x.mode = value
   720  		x.typ = Typ[UnsafePointer]
   721  		if check.recordTypes() {
   722  			check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
   723  		}
   724  
   725  	case _Alignof:
   726  		// unsafe.Alignof(x T) uintptr
   727  		check.assignment(x, nil, "argument to unsafe.Alignof")
   728  		if x.mode == invalid {
   729  			return
   730  		}
   731  
   732  		if hasVarSize(x.typ, nil) {
   733  			x.mode = value
   734  			if check.recordTypes() {
   735  				check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
   736  			}
   737  		} else {
   738  			x.mode = constant_
   739  			x.val = constant.MakeInt64(check.conf.alignof(x.typ))
   740  			// result is constant - no need to record signature
   741  		}
   742  		x.typ = Typ[Uintptr]
   743  
   744  	case _Offsetof:
   745  		// unsafe.Offsetof(x T) uintptr, where x must be a selector
   746  		// (no argument evaluated yet)
   747  		arg0 := argList[0]
   748  		selx, _ := ast.Unparen(arg0).(*ast.SelectorExpr)
   749  		if selx == nil {
   750  			check.errorf(arg0, BadOffsetofSyntax, invalidArg+"%s is not a selector expression", arg0)
   751  			check.use(arg0)
   752  			return
   753  		}
   754  
   755  		check.expr(nil, x, selx.X)
   756  		if x.mode == invalid {
   757  			return
   758  		}
   759  
   760  		base := derefStructPtr(x.typ)
   761  		sel := selx.Sel.Name
   762  		obj, index, indirect := lookupFieldOrMethod(base, false, check.pkg, sel, false)
   763  		switch obj.(type) {
   764  		case nil:
   765  			check.errorf(x, MissingFieldOrMethod, invalidArg+"%s has no single field %s", base, sel)
   766  			return
   767  		case *Func:
   768  			// TODO(gri) Using derefStructPtr may result in methods being found
   769  			// that don't actually exist. An error either way, but the error
   770  			// message is confusing. See: https://play.golang.org/p/al75v23kUy ,
   771  			// but go/types reports: "invalid argument: x.m is a method value".
   772  			check.errorf(arg0, InvalidOffsetof, invalidArg+"%s is a method value", arg0)
   773  			return
   774  		}
   775  		if indirect {
   776  			check.errorf(x, InvalidOffsetof, invalidArg+"field %s is embedded via a pointer in %s", sel, base)
   777  			return
   778  		}
   779  
   780  		// TODO(gri) Should we pass x.typ instead of base (and have indirect report if derefStructPtr indirected)?
   781  		check.recordSelection(selx, FieldVal, base, obj, index, false)
   782  
   783  		// record the selector expression (was bug - go.dev/issue/47895)
   784  		{
   785  			mode := value
   786  			if x.mode == variable || indirect {
   787  				mode = variable
   788  			}
   789  			check.record(&operand{mode, selx, obj.Type(), nil, 0})
   790  		}
   791  
   792  		// The field offset is considered a variable even if the field is declared before
   793  		// the part of the struct which is variable-sized. This makes both the rules
   794  		// simpler and also permits (or at least doesn't prevent) a compiler from re-
   795  		// arranging struct fields if it wanted to.
   796  		if hasVarSize(base, nil) {
   797  			x.mode = value
   798  			if check.recordTypes() {
   799  				check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], obj.Type()))
   800  			}
   801  		} else {
   802  			offs := check.conf.offsetof(base, index)
   803  			if offs < 0 {
   804  				check.errorf(x, TypeTooLarge, "%s is too large", x)
   805  				return
   806  			}
   807  			x.mode = constant_
   808  			x.val = constant.MakeInt64(offs)
   809  			// result is constant - no need to record signature
   810  		}
   811  		x.typ = Typ[Uintptr]
   812  
   813  	case _Sizeof:
   814  		// unsafe.Sizeof(x T) uintptr
   815  		check.assignment(x, nil, "argument to unsafe.Sizeof")
   816  		if x.mode == invalid {
   817  			return
   818  		}
   819  
   820  		if hasVarSize(x.typ, nil) {
   821  			x.mode = value
   822  			if check.recordTypes() {
   823  				check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
   824  			}
   825  		} else {
   826  			size := check.conf.sizeof(x.typ)
   827  			if size < 0 {
   828  				check.errorf(x, TypeTooLarge, "%s is too large", x)
   829  				return
   830  			}
   831  			x.mode = constant_
   832  			x.val = constant.MakeInt64(size)
   833  			// result is constant - no need to record signature
   834  		}
   835  		x.typ = Typ[Uintptr]
   836  
   837  	case _Slice:
   838  		// unsafe.Slice(ptr *T, len IntegerType) []T
   839  		check.verifyVersionf(call.Fun, go1_17, "unsafe.Slice")
   840  
   841  		u, _ := commonUnder(x.typ, nil)
   842  		ptr, _ := u.(*Pointer)
   843  		if ptr == nil {
   844  			check.errorf(x, InvalidUnsafeSlice, invalidArg+"%s is not a pointer", x)
   845  			return
   846  		}
   847  
   848  		y := args[1]
   849  		if !check.isValidIndex(y, InvalidUnsafeSlice, "length", false) {
   850  			return
   851  		}
   852  
   853  		x.mode = value
   854  		x.typ = NewSlice(ptr.base)
   855  		if check.recordTypes() {
   856  			check.recordBuiltinType(call.Fun, makeSig(x.typ, ptr, y.typ))
   857  		}
   858  
   859  	case _SliceData:
   860  		// unsafe.SliceData(slice []T) *T
   861  		check.verifyVersionf(call.Fun, go1_20, "unsafe.SliceData")
   862  
   863  		u, _ := commonUnder(x.typ, nil)
   864  		slice, _ := u.(*Slice)
   865  		if slice == nil {
   866  			check.errorf(x, InvalidUnsafeSliceData, invalidArg+"%s is not a slice", x)
   867  			return
   868  		}
   869  
   870  		x.mode = value
   871  		x.typ = NewPointer(slice.elem)
   872  		if check.recordTypes() {
   873  			check.recordBuiltinType(call.Fun, makeSig(x.typ, slice))
   874  		}
   875  
   876  	case _String:
   877  		// unsafe.String(ptr *byte, len IntegerType) string
   878  		check.verifyVersionf(call.Fun, go1_20, "unsafe.String")
   879  
   880  		check.assignment(x, NewPointer(universeByte), "argument to unsafe.String")
   881  		if x.mode == invalid {
   882  			return
   883  		}
   884  
   885  		y := args[1]
   886  		if !check.isValidIndex(y, InvalidUnsafeString, "length", false) {
   887  			return
   888  		}
   889  
   890  		x.mode = value
   891  		x.typ = Typ[String]
   892  		if check.recordTypes() {
   893  			check.recordBuiltinType(call.Fun, makeSig(x.typ, NewPointer(universeByte), y.typ))
   894  		}
   895  
   896  	case _StringData:
   897  		// unsafe.StringData(str string) *byte
   898  		check.verifyVersionf(call.Fun, go1_20, "unsafe.StringData")
   899  
   900  		check.assignment(x, Typ[String], "argument to unsafe.StringData")
   901  		if x.mode == invalid {
   902  			return
   903  		}
   904  
   905  		x.mode = value
   906  		x.typ = NewPointer(universeByte)
   907  		if check.recordTypes() {
   908  			check.recordBuiltinType(call.Fun, makeSig(x.typ, Typ[String]))
   909  		}
   910  
   911  	case _Assert:
   912  		// assert(pred) causes a typechecker error if pred is false.
   913  		// The result of assert is the value of pred if there is no error.
   914  		// Note: assert is only available in self-test mode.
   915  		if x.mode != constant_ || !isBoolean(x.typ) {
   916  			check.errorf(x, Test, invalidArg+"%s is not a boolean constant", x)
   917  			return
   918  		}
   919  		if x.val.Kind() != constant.Bool {
   920  			check.errorf(x, Test, "internal error: value of %s should be a boolean constant", x)
   921  			return
   922  		}
   923  		if !constant.BoolVal(x.val) {
   924  			check.errorf(call, Test, "%v failed", call)
   925  			// compile-time assertion failure - safe to continue
   926  		}
   927  		// result is constant - no need to record signature
   928  
   929  	case _Trace:
   930  		// trace(x, y, z, ...) dumps the positions, expressions, and
   931  		// values of its arguments. The result of trace is the value
   932  		// of the first argument.
   933  		// Note: trace is only available in self-test mode.
   934  		// (no argument evaluated yet)
   935  		if nargs == 0 {
   936  			check.dump("%v: trace() without arguments", call.Pos())
   937  			x.mode = novalue
   938  			break
   939  		}
   940  		var t operand
   941  		x1 := x
   942  		for _, arg := range argList {
   943  			check.rawExpr(nil, x1, arg, nil, false) // permit trace for types, e.g.: new(trace(T))
   944  			check.dump("%v: %s", x1.Pos(), x1)
   945  			x1 = &t // use incoming x only for first argument
   946  		}
   947  		if x.mode == invalid {
   948  			return
   949  		}
   950  		// trace is only available in test mode - no need to record signature
   951  
   952  	default:
   953  		panic("unreachable")
   954  	}
   955  
   956  	assert(x.mode != invalid)
   957  	return true
   958  }
   959  
   960  // sliceElem returns the slice element type for a slice operand x
   961  // or a type error if x is not a slice (or a type set of slices).
   962  func sliceElem(x *operand) (Type, *typeError) {
   963  	var E Type
   964  	var err *typeError
   965  	typeset(x.typ, func(_, u Type) bool {
   966  		s, _ := u.(*Slice)
   967  		if s == nil {
   968  			if x.isNil() {
   969  				// Printing x in this case would just print "nil".
   970  				// Special case this so we can emphasize "untyped".
   971  				err = typeErrorf("argument must be a slice; have untyped nil")
   972  			} else {
   973  				err = typeErrorf("argument must be a slice; have %s", x)
   974  			}
   975  			return false
   976  		}
   977  		if E == nil {
   978  			E = s.elem
   979  		} else if !Identical(E, s.elem) {
   980  			err = typeErrorf("mismatched slice element types %s and %s in %s", E, s.elem, x)
   981  			return false
   982  		}
   983  		return true
   984  	})
   985  	if err != nil {
   986  		return nil, err
   987  	}
   988  	return E, nil
   989  }
   990  
   991  // hasVarSize reports if the size of type t is variable due to type parameters
   992  // or if the type is infinitely-sized due to a cycle for which the type has not
   993  // yet been checked.
   994  func hasVarSize(t Type, seen map[*Named]bool) (varSized bool) {
   995  	// Cycles are only possible through *Named types.
   996  	// The seen map is used to detect cycles and track
   997  	// the results of previously seen types.
   998  	if named := asNamed(t); named != nil {
   999  		if v, ok := seen[named]; ok {
  1000  			return v
  1001  		}
  1002  		if seen == nil {
  1003  			seen = make(map[*Named]bool)
  1004  		}
  1005  		seen[named] = true // possibly cyclic until proven otherwise
  1006  		defer func() {
  1007  			seen[named] = varSized // record final determination for named
  1008  		}()
  1009  	}
  1010  
  1011  	switch u := under(t).(type) {
  1012  	case *Array:
  1013  		return hasVarSize(u.elem, seen)
  1014  	case *Struct:
  1015  		for _, f := range u.fields {
  1016  			if hasVarSize(f.typ, seen) {
  1017  				return true
  1018  			}
  1019  		}
  1020  	case *Interface:
  1021  		return isTypeParam(t)
  1022  	case *Named, *Union:
  1023  		panic("unreachable")
  1024  	}
  1025  	return false
  1026  }
  1027  
  1028  // applyTypeFunc applies f to x. If x is a type parameter,
  1029  // the result is a type parameter constrained by a new
  1030  // interface bound. The type bounds for that interface
  1031  // are computed by applying f to each of the type bounds
  1032  // of x. If any of these applications of f return nil,
  1033  // applyTypeFunc returns nil.
  1034  // If x is not a type parameter, the result is f(x).
  1035  func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId) Type {
  1036  	if tp, _ := Unalias(x.typ).(*TypeParam); tp != nil {
  1037  		// Test if t satisfies the requirements for the argument
  1038  		// type and collect possible result types at the same time.
  1039  		var terms []*Term
  1040  		if !tp.is(func(t *term) bool {
  1041  			if t == nil {
  1042  				return false
  1043  			}
  1044  			if r := f(t.typ); r != nil {
  1045  				terms = append(terms, NewTerm(t.tilde, r))
  1046  				return true
  1047  			}
  1048  			return false
  1049  		}) {
  1050  			return nil
  1051  		}
  1052  
  1053  		// We can type-check this fine but we're introducing a synthetic
  1054  		// type parameter for the result. It's not clear what the API
  1055  		// implications are here. Report an error for 1.18 (see go.dev/issue/50912),
  1056  		// but continue type-checking.
  1057  		var code Code
  1058  		switch id {
  1059  		case _Real:
  1060  			code = InvalidReal
  1061  		case _Imag:
  1062  			code = InvalidImag
  1063  		case _Complex:
  1064  			code = InvalidComplex
  1065  		default:
  1066  			panic("unreachable")
  1067  		}
  1068  		check.softErrorf(x, code, "%s not supported as argument to built-in %s for go1.18 (see go.dev/issue/50937)", x, predeclaredFuncs[id].name)
  1069  
  1070  		// Construct a suitable new type parameter for the result type.
  1071  		// The type parameter is placed in the current package so export/import
  1072  		// works as expected.
  1073  		tpar := NewTypeName(nopos, check.pkg, tp.obj.name, nil)
  1074  		ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect
  1075  		ptyp.index = tp.index
  1076  
  1077  		return ptyp
  1078  	}
  1079  
  1080  	return f(x.typ)
  1081  }
  1082  
  1083  // makeSig makes a signature for the given argument and result types.
  1084  // Default types are used for untyped arguments, and res may be nil.
  1085  func makeSig(res Type, args ...Type) *Signature {
  1086  	list := make([]*Var, len(args))
  1087  	for i, param := range args {
  1088  		list[i] = NewParam(nopos, nil, "", Default(param))
  1089  	}
  1090  	params := NewTuple(list...)
  1091  	var result *Tuple
  1092  	if res != nil {
  1093  		assert(!isUntyped(res))
  1094  		result = NewTuple(newVar(ResultVar, nopos, nil, "", res))
  1095  	}
  1096  	return &Signature{params: params, results: result}
  1097  }
  1098  
  1099  // arrayPtrDeref returns A if typ is of the form *A and A is an array;
  1100  // otherwise it returns typ.
  1101  func arrayPtrDeref(typ Type) Type {
  1102  	if p, ok := Unalias(typ).(*Pointer); ok {
  1103  		if a, _ := under(p.base).(*Array); a != nil {
  1104  			return a
  1105  		}
  1106  	}
  1107  	return typ
  1108  }
  1109  

View as plain text