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

View as plain text