builtins.go raw

   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 ...E) S, where E is the element type of S
  89  		// spec: "The variadic function append appends zero or more values x to
  90  		// a slice s of type S and returns the resulting slice, also of type S.
  91  		// The values x are passed to a parameter of type ...E where E is the
  92  		// element type of S and the respective parameter passing rules apply.
  93  		// As a special case, append also accepts a first argument assignable
  94  		// to type []byte with a second argument of string type followed by ... .
  95  		// This form appends the bytes of the string."
  96  
  97  		// Handle append(bytes, y...) special case, where
  98  		// the type set of y is {string} or {string, []byte}.
  99  		var sig *Signature
 100  		if nargs == 2 && hasDots(call) {
 101  			if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
 102  				y := args[1]
 103  				hasString := false
 104  				typeset(y.typ, func(_, u Type) bool {
 105  					if s, _ := u.(*Slice); s != nil && Identical(s.elem, universeByte) {
 106  						return true
 107  					}
 108  					if isString(u) {
 109  						hasString = true
 110  						return true
 111  					}
 112  					y = nil
 113  					return false
 114  				})
 115  				if y != nil && hasString {
 116  					// setting the signature also signals that we're done
 117  					sig = makeSig(x.typ, x.typ, y.typ)
 118  					sig.variadic = true
 119  				}
 120  			}
 121  		}
 122  
 123  		// general case
 124  		if sig == nil {
 125  			// spec: "If S is a type parameter, all types in its type set
 126  			// must have the same underlying slice type []E."
 127  			E, err := sliceElem(x)
 128  			if err != nil {
 129  				check.errorf(x, InvalidAppend, "invalid append: %s", err.format(check))
 130  				return
 131  			}
 132  			// check arguments by creating custom signature
 133  			sig = makeSig(x.typ, x.typ, NewSlice(E)) // []E required for variadic signature
 134  			sig.variadic = true
 135  			check.arguments(call, sig, nil, nil, args, nil) // discard result (we know the result type)
 136  			// ok to continue even if check.arguments reported errors
 137  		}
 138  
 139  		if check.recordTypes() {
 140  			check.recordBuiltinType(call.Fun, sig)
 141  		}
 142  		x.mode = value
 143  		// x.typ is unchanged
 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 underIs(x.typ, func(u Type) bool {
 189  				switch t := arrayPtrDeref(u).(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 built-in %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 []E) int
 361  		// spec: "The function copy copies slice elements from a source src to a destination
 362  		// dst and returns the number of elements copied. Both arguments must have identical
 363  		// element type E and must be assignable to a slice of type []E.
 364  		// The number of elements copied is the minimum of len(src) and len(dst).
 365  		// As a special case, copy also accepts a destination argument assignable to type
 366  		// []byte with a source argument of a string type.
 367  		// This form copies the bytes from the string into the byte slice."
 368  
 369  		// get special case out of the way
 370  		y := args[1]
 371  		var special bool
 372  		if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
 373  			special = true
 374  			typeset(y.typ, func(_, u Type) bool {
 375  				if s, _ := u.(*Slice); s != nil && Identical(s.elem, universeByte) {
 376  					return true
 377  				}
 378  				if isString(u) {
 379  					return true
 380  				}
 381  				special = false
 382  				return false
 383  			})
 384  		}
 385  
 386  		// general case
 387  		if !special {
 388  			// spec: "If the type of one or both arguments is a type parameter, all types
 389  			// in their respective type sets must have the same underlying slice type []E."
 390  			dstE, err := sliceElem(x)
 391  			if err != nil {
 392  				check.errorf(x, InvalidCopy, "invalid copy: %s", err.format(check))
 393  				return
 394  			}
 395  			srcE, err := sliceElem(y)
 396  			if err != nil {
 397  				// If we have a string, for a better error message proceed with byte element type.
 398  				if !allString(y.typ) {
 399  					check.errorf(y, InvalidCopy, "invalid copy: %s", err.format(check))
 400  					return
 401  				}
 402  				srcE = universeByte
 403  			}
 404  			if !Identical(dstE, srcE) {
 405  				check.errorf(x, InvalidCopy, "invalid copy: arguments %s and %s have different element types %s and %s", x, y, dstE, srcE)
 406  				return
 407  			}
 408  		}
 409  
 410  		if check.recordTypes() {
 411  			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
 412  		}
 413  		x.mode = value
 414  		x.typ = Typ[Int]
 415  
 416  	case _Delete:
 417  		// delete(map_, key)
 418  		// map_ must be a map type or a type parameter describing map types.
 419  		// The key cannot be a type parameter for now.
 420  		map_ := x.typ
 421  		var key Type
 422  		if !underIs(map_, func(u Type) bool {
 423  			map_, _ := u.(*Map)
 424  			if map_ == nil {
 425  				check.errorf(x, InvalidDelete, invalidArg+"%s is not a map", x)
 426  				return false
 427  			}
 428  			if key != nil && !Identical(map_.key, key) {
 429  				check.errorf(x, InvalidDelete, invalidArg+"maps of %s must have identical key types", x)
 430  				return false
 431  			}
 432  			key = map_.key
 433  			return true
 434  		}) {
 435  			return
 436  		}
 437  
 438  		*x = *args[1] // key
 439  		check.assignment(x, key, "argument to delete")
 440  		if x.mode == invalid {
 441  			return
 442  		}
 443  
 444  		x.mode = novalue
 445  		if check.recordTypes() {
 446  			check.recordBuiltinType(call.Fun, makeSig(nil, map_, key))
 447  		}
 448  
 449  	case _Imag, _Real:
 450  		// imag(complexT) floatT
 451  		// real(complexT) floatT
 452  
 453  		// convert or check untyped argument
 454  		if isUntyped(x.typ) {
 455  			if x.mode == constant_ {
 456  				// an untyped constant number can always be considered
 457  				// as a complex constant
 458  				if isNumeric(x.typ) {
 459  					x.typ = Typ[UntypedComplex]
 460  				}
 461  			} else {
 462  				// an untyped non-constant argument may appear if
 463  				// it contains a (yet untyped non-constant) shift
 464  				// expression: convert it to complex128 which will
 465  				// result in an error (shift of complex value)
 466  				check.convertUntyped(x, Typ[Complex128])
 467  				// x should be invalid now, but be conservative and check
 468  				if x.mode == invalid {
 469  					return
 470  				}
 471  			}
 472  		}
 473  
 474  		// the argument must be of complex type
 475  		// (applyTypeFunc never calls f with a type parameter)
 476  		f := func(typ Type) Type {
 477  			assert(!isTypeParam(typ))
 478  			if t, _ := under(typ).(*Basic); t != nil {
 479  				switch t.kind {
 480  				case Complex64:
 481  					return Typ[Float32]
 482  				case Complex128:
 483  					return Typ[Float64]
 484  				case UntypedComplex:
 485  					return Typ[UntypedFloat]
 486  				}
 487  			}
 488  			return nil
 489  		}
 490  		resTyp := check.applyTypeFunc(f, x, id)
 491  		if resTyp == nil {
 492  			code := InvalidImag
 493  			if id == _Real {
 494  				code = InvalidReal
 495  			}
 496  			check.errorf(x, code, invalidArg+"argument has type %s, expected complex type", x.typ)
 497  			return
 498  		}
 499  
 500  		// if the argument is a constant, the result is a constant
 501  		if x.mode == constant_ {
 502  			if id == _Real {
 503  				x.val = constant.Real(x.val)
 504  			} else {
 505  				x.val = constant.Imag(x.val)
 506  			}
 507  		} else {
 508  			x.mode = value
 509  		}
 510  
 511  		if check.recordTypes() && x.mode != constant_ {
 512  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
 513  		}
 514  
 515  		x.typ = resTyp
 516  
 517  	case _Make:
 518  		// make(T, n)
 519  		// make(T, n, m)
 520  		// (no argument evaluated yet)
 521  		arg0 := argList[0]
 522  		T := check.varType(arg0)
 523  		if !isValid(T) {
 524  			return
 525  		}
 526  
 527  		u, err := commonUnder(T, func(_, u Type) *typeError {
 528  			switch u.(type) {
 529  			case *Slice, *Map, *Chan:
 530  				return nil // ok
 531  			case nil:
 532  				return typeErrorf("no specific type")
 533  			default:
 534  				return typeErrorf("type must be slice, map, or channel")
 535  			}
 536  		})
 537  		if err != nil {
 538  			check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: %s", arg0, err.format(check))
 539  			return
 540  		}
 541  
 542  		var min int // minimum number of arguments
 543  		switch u.(type) {
 544  		case *Slice:
 545  			min = 2
 546  		case *Map, *Chan:
 547  			min = 1
 548  		default:
 549  			// any other type was excluded above
 550  			panic("unreachable")
 551  		}
 552  		if nargs < min || min+1 < nargs {
 553  			check.errorf(call, WrongArgCount, invalidOp+"%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
 554  			return
 555  		}
 556  
 557  		types := []Type{T}
 558  		var sizes []int64 // constant integer arguments, if any
 559  		for _, arg := range argList[1:] {
 560  			typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
 561  			types = append(types, typ)
 562  			if size >= 0 {
 563  				sizes = append(sizes, size)
 564  			}
 565  		}
 566  		if len(sizes) == 2 && sizes[0] > sizes[1] {
 567  			check.error(argList[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
 568  			// safe to continue
 569  		}
 570  		x.mode = value
 571  		x.typ = T
 572  		if check.recordTypes() {
 573  			check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
 574  		}
 575  
 576  	case _Max, _Min:
 577  		// max(x, ...)
 578  		// min(x, ...)
 579  		check.verifyVersionf(call.Fun, go1_21, "built-in %s", bin.name)
 580  
 581  		op := token.LSS
 582  		if id == _Max {
 583  			op = token.GTR
 584  		}
 585  
 586  		for i, a := range args {
 587  			if a.mode == invalid {
 588  				return
 589  			}
 590  
 591  			if !allOrdered(a.typ) {
 592  				check.errorf(a, InvalidMinMaxOperand, invalidArg+"%s cannot be ordered", a)
 593  				return
 594  			}
 595  
 596  			// The first argument is already in x and there's nothing left to do.
 597  			if i > 0 {
 598  				check.matchTypes(x, a)
 599  				if x.mode == invalid {
 600  					return
 601  				}
 602  
 603  				if !Identical(x.typ, a.typ) {
 604  					check.errorf(a, MismatchedTypes, invalidArg+"mismatched types %s (previous argument) and %s (type of %s)", x.typ, a.typ, a.expr)
 605  					return
 606  				}
 607  
 608  				if x.mode == constant_ && a.mode == constant_ {
 609  					if constant.Compare(a.val, op, x.val) {
 610  						*x = *a
 611  					}
 612  				} else {
 613  					x.mode = value
 614  				}
 615  			}
 616  		}
 617  
 618  		// If nargs == 1, make sure x.mode is either a value or a constant.
 619  		if x.mode != constant_ {
 620  			x.mode = value
 621  			// A value must not be untyped.
 622  			check.assignment(x, &emptyInterface, "argument to built-in "+bin.name)
 623  			if x.mode == invalid {
 624  				return
 625  			}
 626  		}
 627  
 628  		// Use the final type computed above for all arguments.
 629  		for _, a := range args {
 630  			check.updateExprType(a.expr, x.typ, true)
 631  		}
 632  
 633  		if check.recordTypes() && x.mode != constant_ {
 634  			types := make([]Type, nargs)
 635  			for i := range types {
 636  				types[i] = x.typ
 637  			}
 638  			check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
 639  		}
 640  
 641  	case _New:
 642  		// new(T)
 643  		// (no argument evaluated yet)
 644  		T := check.varType(argList[0])
 645  		if !isValid(T) {
 646  			return
 647  		}
 648  
 649  		x.mode = value
 650  		x.typ = &Pointer{base: T}
 651  		if check.recordTypes() {
 652  			check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
 653  		}
 654  
 655  	case _Panic:
 656  		// panic(x)
 657  		// record panic call if inside a function with result parameters
 658  		// (for use in Checker.isTerminating)
 659  		if check.sig != nil && check.sig.results.Len() > 0 {
 660  			// function has result parameters
 661  			p := check.isPanic
 662  			if p == nil {
 663  				// allocate lazily
 664  				p = make(map[*ast.CallExpr]bool)
 665  				check.isPanic = p
 666  			}
 667  			p[call] = true
 668  		}
 669  
 670  		check.assignment(x, &emptyInterface, "argument to panic")
 671  		if x.mode == invalid {
 672  			return
 673  		}
 674  
 675  		x.mode = novalue
 676  		if check.recordTypes() {
 677  			check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
 678  		}
 679  
 680  	case _Print, _Println:
 681  		// print(x, y, ...)
 682  		// println(x, y, ...)
 683  		var params []Type
 684  		if nargs > 0 {
 685  			params = make([]Type, nargs)
 686  			for i, a := range args {
 687  				check.assignment(a, nil, "argument to built-in "+predeclaredFuncs[id].name)
 688  				if a.mode == invalid {
 689  					return
 690  				}
 691  				params[i] = a.typ
 692  			}
 693  		}
 694  
 695  		x.mode = novalue
 696  		if check.recordTypes() {
 697  			check.recordBuiltinType(call.Fun, makeSig(nil, params...))
 698  		}
 699  
 700  	case _Recover:
 701  		// recover() interface{}
 702  		x.mode = value
 703  		x.typ = &emptyInterface
 704  		if check.recordTypes() {
 705  			check.recordBuiltinType(call.Fun, makeSig(x.typ))
 706  		}
 707  
 708  	case _Spawn:
 709  		// spawn(fn, args...) chan struct{}
 710  		// spawn("transport", fn, args...) chan struct{}
 711  		// First argument must be a function or a transport string constant.
 712  		// Remaining arguments are validated by the compiler at SSA level
 713  		// (must implement moxie.Codec, channels must have Codec element types).
 714  		if nargs < 1 {
 715  			return
 716  		}
 717  		if _, ok := under(x.typ).(*Signature); !ok {
 718  			if !isString(x.typ) {
 719  				check.errorf(x, InvalidCall, invalidOp+"first argument to spawn must be a function or transport string, got %s", x)
 720  				return
 721  			}
 722  			// Transport string — second arg must be a function.
 723  			if nargs < 2 {
 724  				check.errorf(x, WrongArgCount, invalidOp+"spawn with transport string requires a function argument")
 725  				return
 726  			}
 727  			if _, ok := under(args[1].typ).(*Signature); !ok {
 728  				check.errorf(args[1], InvalidCall, invalidOp+"second argument to spawn must be a function when first is a transport string, got %s", args[1])
 729  				return
 730  			}
 731  		}
 732  		x.mode = value
 733  		x.typ = NewChan(SendRecv, NewStruct(nil, nil))
 734  		// Synthesize a signature for the spawn ident so the SSA builder
 735  		// can construct a *Builtin with a *types.Signature when it visits
 736  		// the call. Without this, fn.instanceType(e).(*types.Signature)
 737  		// at builder.go:814 panics: the universe entry has no signature.
 738  		if check.recordTypes() {
 739  			params := make([]Type, nargs)
 740  			for i, a := range args {
 741  				params[i] = a.typ
 742  			}
 743  			check.recordBuiltinType(call.Fun, makeSig(x.typ, params...))
 744  		}
 745  
 746  	case _Free:
 747  		// free(x) - deterministic deallocation
 748  		x.mode = novalue
 749  		if check.recordTypes() {
 750  			check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
 751  		}
 752  
 753  	case _Add:
 754  		// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
 755  		check.verifyVersionf(call.Fun, go1_17, "unsafe.Add")
 756  
 757  		check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
 758  		if x.mode == invalid {
 759  			return
 760  		}
 761  
 762  		y := args[1]
 763  		if !check.isValidIndex(y, InvalidUnsafeAdd, "length", true) {
 764  			return
 765  		}
 766  
 767  		x.mode = value
 768  		x.typ = Typ[UnsafePointer]
 769  		if check.recordTypes() {
 770  			check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
 771  		}
 772  
 773  	case _Alignof:
 774  		// unsafe.Alignof(x T) uintptr
 775  		check.assignment(x, nil, "argument to unsafe.Alignof")
 776  		if x.mode == invalid {
 777  			return
 778  		}
 779  
 780  		if hasVarSize(x.typ, nil) {
 781  			x.mode = value
 782  			if check.recordTypes() {
 783  				check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
 784  			}
 785  		} else {
 786  			x.mode = constant_
 787  			x.val = constant.MakeInt64(check.conf.alignof(x.typ))
 788  			// result is constant - no need to record signature
 789  		}
 790  		x.typ = Typ[Uintptr]
 791  
 792  	case _Offsetof:
 793  		// unsafe.Offsetof(x T) uintptr, where x must be a selector
 794  		// (no argument evaluated yet)
 795  		arg0 := argList[0]
 796  		selx, _ := ast.Unparen(arg0).(*ast.SelectorExpr)
 797  		if selx == nil {
 798  			check.errorf(arg0, BadOffsetofSyntax, invalidArg+"%s is not a selector expression", arg0)
 799  			check.use(arg0)
 800  			return
 801  		}
 802  
 803  		check.expr(nil, x, selx.X)
 804  		if x.mode == invalid {
 805  			return
 806  		}
 807  
 808  		base := derefStructPtr(x.typ)
 809  		sel := selx.Sel.Name
 810  		obj, index, indirect := lookupFieldOrMethod(base, false, check.pkg, sel, false)
 811  		switch obj.(type) {
 812  		case nil:
 813  			check.errorf(x, MissingFieldOrMethod, invalidArg+"%s has no single field %s", base, sel)
 814  			return
 815  		case *Func:
 816  			// TODO(gri) Using derefStructPtr may result in methods being found
 817  			// that don't actually exist. An error either way, but the error
 818  			// message is confusing. See: https://play.golang.org/p/al75v23kUy ,
 819  			// but go/types reports: "invalid argument: x.m is a method value".
 820  			check.errorf(arg0, InvalidOffsetof, invalidArg+"%s is a method value", arg0)
 821  			return
 822  		}
 823  		if indirect {
 824  			check.errorf(x, InvalidOffsetof, invalidArg+"field %s is embedded via a pointer in %s", sel, base)
 825  			return
 826  		}
 827  
 828  		// TODO(gri) Should we pass x.typ instead of base (and have indirect report if derefStructPtr indirected)?
 829  		check.recordSelection(selx, FieldVal, base, obj, index, false)
 830  
 831  		// record the selector expression (was bug - go.dev/issue/47895)
 832  		{
 833  			mode := value
 834  			if x.mode == variable || indirect {
 835  				mode = variable
 836  			}
 837  			check.record(&operand{mode, selx, obj.Type(), nil, 0})
 838  		}
 839  
 840  		// The field offset is considered a variable even if the field is declared before
 841  		// the part of the struct which is variable-sized. This makes both the rules
 842  		// simpler and also permits (or at least doesn't prevent) a compiler from re-
 843  		// arranging struct fields if it wanted to.
 844  		if hasVarSize(base, nil) {
 845  			x.mode = value
 846  			if check.recordTypes() {
 847  				check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], obj.Type()))
 848  			}
 849  		} else {
 850  			offs := check.conf.offsetof(base, index)
 851  			if offs < 0 {
 852  				check.errorf(x, TypeTooLarge, "%s is too large", x)
 853  				return
 854  			}
 855  			x.mode = constant_
 856  			x.val = constant.MakeInt64(offs)
 857  			// result is constant - no need to record signature
 858  		}
 859  		x.typ = Typ[Uintptr]
 860  
 861  	case _Sizeof:
 862  		// unsafe.Sizeof(x T) uintptr
 863  		check.assignment(x, nil, "argument to unsafe.Sizeof")
 864  		if x.mode == invalid {
 865  			return
 866  		}
 867  
 868  		if hasVarSize(x.typ, nil) {
 869  			x.mode = value
 870  			if check.recordTypes() {
 871  				check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
 872  			}
 873  		} else {
 874  			size := check.conf.sizeof(x.typ)
 875  			if size < 0 {
 876  				check.errorf(x, TypeTooLarge, "%s is too large", x)
 877  				return
 878  			}
 879  			x.mode = constant_
 880  			x.val = constant.MakeInt64(size)
 881  			// result is constant - no need to record signature
 882  		}
 883  		x.typ = Typ[Uintptr]
 884  
 885  	case _Slice:
 886  		// unsafe.Slice(ptr *T, len IntegerType) []T
 887  		check.verifyVersionf(call.Fun, go1_17, "unsafe.Slice")
 888  
 889  		u, _ := commonUnder(x.typ, nil)
 890  		ptr, _ := u.(*Pointer)
 891  		if ptr == nil {
 892  			check.errorf(x, InvalidUnsafeSlice, invalidArg+"%s is not a pointer", x)
 893  			return
 894  		}
 895  
 896  		y := args[1]
 897  		if !check.isValidIndex(y, InvalidUnsafeSlice, "length", false) {
 898  			return
 899  		}
 900  
 901  		x.mode = value
 902  		x.typ = NewSlice(ptr.base)
 903  		if check.recordTypes() {
 904  			check.recordBuiltinType(call.Fun, makeSig(x.typ, ptr, y.typ))
 905  		}
 906  
 907  	case _SliceData:
 908  		// unsafe.SliceData(slice []T) *T
 909  		check.verifyVersionf(call.Fun, go1_20, "unsafe.SliceData")
 910  
 911  		u, _ := commonUnder(x.typ, nil)
 912  		slice, _ := u.(*Slice)
 913  		if slice == nil {
 914  			check.errorf(x, InvalidUnsafeSliceData, invalidArg+"%s is not a slice", x)
 915  			return
 916  		}
 917  
 918  		x.mode = value
 919  		x.typ = NewPointer(slice.elem)
 920  		if check.recordTypes() {
 921  			check.recordBuiltinType(call.Fun, makeSig(x.typ, slice))
 922  		}
 923  
 924  	case _String:
 925  		// unsafe.String(ptr *byte, len IntegerType) string
 926  		check.verifyVersionf(call.Fun, go1_20, "unsafe.String")
 927  
 928  		check.assignment(x, NewPointer(universeByte), "argument to unsafe.String")
 929  		if x.mode == invalid {
 930  			return
 931  		}
 932  
 933  		y := args[1]
 934  		if !check.isValidIndex(y, InvalidUnsafeString, "length", false) {
 935  			return
 936  		}
 937  
 938  		x.mode = value
 939  		x.typ = Typ[String]
 940  		if check.recordTypes() {
 941  			check.recordBuiltinType(call.Fun, makeSig(x.typ, NewPointer(universeByte), y.typ))
 942  		}
 943  
 944  	case _StringData:
 945  		// unsafe.StringData(str string) *byte
 946  		check.verifyVersionf(call.Fun, go1_20, "unsafe.StringData")
 947  
 948  		check.assignment(x, Typ[String], "argument to unsafe.StringData")
 949  		if x.mode == invalid {
 950  			return
 951  		}
 952  
 953  		x.mode = value
 954  		x.typ = NewPointer(universeByte)
 955  		if check.recordTypes() {
 956  			check.recordBuiltinType(call.Fun, makeSig(x.typ, Typ[String]))
 957  		}
 958  
 959  	case _Assert:
 960  		// assert(pred) causes a typechecker error if pred is false.
 961  		// The result of assert is the value of pred if there is no error.
 962  		// Note: assert is only available in self-test mode.
 963  		if x.mode != constant_ || !isBoolean(x.typ) {
 964  			check.errorf(x, Test, invalidArg+"%s is not a boolean constant", x)
 965  			return
 966  		}
 967  		if x.val.Kind() != constant.Bool {
 968  			check.errorf(x, Test, "internal error: value of %s should be a boolean constant", x)
 969  			return
 970  		}
 971  		if !constant.BoolVal(x.val) {
 972  			check.errorf(call, Test, "%v failed", call)
 973  			// compile-time assertion failure - safe to continue
 974  		}
 975  		// result is constant - no need to record signature
 976  
 977  	case _Trace:
 978  		// trace(x, y, z, ...) dumps the positions, expressions, and
 979  		// values of its arguments. The result of trace is the value
 980  		// of the first argument.
 981  		// Note: trace is only available in self-test mode.
 982  		// (no argument evaluated yet)
 983  		if nargs == 0 {
 984  			check.dump("%v: trace() without arguments", call.Pos())
 985  			x.mode = novalue
 986  			break
 987  		}
 988  		var t operand
 989  		x1 := x
 990  		for _, arg := range argList {
 991  			check.rawExpr(nil, x1, arg, nil, false) // permit trace for types, e.g.: new(trace(T))
 992  			check.dump("%v: %s", x1.Pos(), x1)
 993  			x1 = &t // use incoming x only for first argument
 994  		}
 995  		if x.mode == invalid {
 996  			return
 997  		}
 998  		// trace is only available in test mode - no need to record signature
 999  
1000  	default:
1001  		panic("unreachable")
1002  	}
1003  
1004  	assert(x.mode != invalid)
1005  	return true
1006  }
1007  
1008  // sliceElem returns the slice element type for a slice operand x
1009  // or a type error if x is not a slice (or a type set of slices).
1010  func sliceElem(x *operand) (Type, *typeError) {
1011  	var E Type
1012  	var err *typeError
1013  	typeset(x.typ, func(_, u Type) bool {
1014  		s, _ := u.(*Slice)
1015  		if s == nil {
1016  			if x.isNil() {
1017  				// Printing x in this case would just print "nil".
1018  				// Special case this so we can emphasize "untyped".
1019  				err = typeErrorf("argument must be a slice; have untyped nil")
1020  			} else {
1021  				err = typeErrorf("argument must be a slice; have %s", x)
1022  			}
1023  			return false
1024  		}
1025  		if E == nil {
1026  			E = s.elem
1027  		} else if !Identical(E, s.elem) {
1028  			err = typeErrorf("mismatched slice element types %s and %s in %s", E, s.elem, x)
1029  			return false
1030  		}
1031  		return true
1032  	})
1033  	if err != nil {
1034  		return nil, err
1035  	}
1036  	return E, nil
1037  }
1038  
1039  // hasVarSize reports if the size of type t is variable due to type parameters
1040  // or if the type is infinitely-sized due to a cycle for which the type has not
1041  // yet been checked.
1042  func hasVarSize(t Type, seen map[*Named]bool) (varSized bool) {
1043  	// Cycles are only possible through *Named types.
1044  	// The seen map is used to detect cycles and track
1045  	// the results of previously seen types.
1046  	if named := asNamed(t); named != nil {
1047  		if v, ok := seen[named]; ok {
1048  			return v
1049  		}
1050  		if seen == nil {
1051  			seen = make(map[*Named]bool)
1052  		}
1053  		seen[named] = true // possibly cyclic until proven otherwise
1054  		defer func() {
1055  			seen[named] = varSized // record final determination for named
1056  		}()
1057  	}
1058  
1059  	switch u := under(t).(type) {
1060  	case *Array:
1061  		return hasVarSize(u.elem, seen)
1062  	case *Struct:
1063  		for _, f := range u.fields {
1064  			if hasVarSize(f.typ, seen) {
1065  				return true
1066  			}
1067  		}
1068  	case *Interface:
1069  		return isTypeParam(t)
1070  	case *Named, *Union:
1071  		panic("unreachable")
1072  	}
1073  	return false
1074  }
1075  
1076  // applyTypeFunc applies f to x. If x is a type parameter,
1077  // the result is a type parameter constrained by a new
1078  // interface bound. The type bounds for that interface
1079  // are computed by applying f to each of the type bounds
1080  // of x. If any of these applications of f return nil,
1081  // applyTypeFunc returns nil.
1082  // If x is not a type parameter, the result is f(x).
1083  func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId) Type {
1084  	if tp, _ := Unalias(x.typ).(*TypeParam); tp != nil {
1085  		// Test if t satisfies the requirements for the argument
1086  		// type and collect possible result types at the same time.
1087  		var terms []*Term
1088  		if !tp.is(func(t *term) bool {
1089  			if t == nil {
1090  				return false
1091  			}
1092  			if r := f(t.typ); r != nil {
1093  				terms = append(terms, NewTerm(t.tilde, r))
1094  				return true
1095  			}
1096  			return false
1097  		}) {
1098  			return nil
1099  		}
1100  
1101  		// We can type-check this fine but we're introducing a synthetic
1102  		// type parameter for the result. It's not clear what the API
1103  		// implications are here. Report an error for 1.18 (see go.dev/issue/50912),
1104  		// but continue type-checking.
1105  		var code Code
1106  		switch id {
1107  		case _Real:
1108  			code = InvalidReal
1109  		case _Imag:
1110  			code = InvalidImag
1111  		case _Complex:
1112  			code = InvalidComplex
1113  		default:
1114  			panic("unreachable")
1115  		}
1116  		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)
1117  
1118  		// Construct a suitable new type parameter for the result type.
1119  		// The type parameter is placed in the current package so export/import
1120  		// works as expected.
1121  		tpar := NewTypeName(nopos, check.pkg, tp.obj.name, nil)
1122  		ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)})) // assigns type to tpar as a side-effect
1123  		ptyp.index = tp.index
1124  
1125  		return ptyp
1126  	}
1127  
1128  	return f(x.typ)
1129  }
1130  
1131  // makeSig makes a signature for the given argument and result types.
1132  // Default types are used for untyped arguments, and res may be nil.
1133  func makeSig(res Type, args ...Type) *Signature {
1134  	list := make([]*Var, len(args))
1135  	for i, param := range args {
1136  		list[i] = NewParam(nopos, nil, "", Default(param))
1137  	}
1138  	params := NewTuple(list...)
1139  	var result *Tuple
1140  	if res != nil {
1141  		assert(!isUntyped(res))
1142  		result = NewTuple(newVar(ResultVar, nopos, nil, "", res))
1143  	}
1144  	return &Signature{params: params, results: result}
1145  }
1146  
1147  // arrayPtrDeref returns A if typ is of the form *A and A is an array;
1148  // otherwise it returns typ.
1149  func arrayPtrDeref(typ Type) Type {
1150  	if p, ok := Unalias(typ).(*Pointer); ok {
1151  		if a, _ := under(p.base).(*Array); a != nil {
1152  			return a
1153  		}
1154  	}
1155  	return typ
1156  }
1157