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

View as plain text