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

View as plain text