Source file src/cmd/compile/internal/types2/builtins.go

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

View as plain text