github.com/bir3/gocompiler@v0.3.205/src/go/types/builtins.go (about)

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