...

Source file src/go/types/builtins.go

Documentation: go/types

		 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  	"go/ast"
		11  	"go/constant"
		12  	"go/token"
		13  )
		14  
		15  // builtin type-checks a call to the built-in specified by id and
		16  // reports whether the call is valid, with *x holding the result;
		17  // but x.expr is not set. If the call is invalid, the result is
		18  // false, and *x is undefined.
		19  //
		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.invalidOp(atPos(call.Ellipsis),
		25  			_InvalidDotDotDot,
		26  			"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]; x.typ = expand(x.typ) }
		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.invalidOp(inNode(call, call.Rparen), _WrongArgCount, "%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 := asSlice(S); s != nil {
		87  			T = s.elem
		88  		} else {
		89  			check.invalidArg(x, _InvalidAppend, "%s is not a slice", x)
		90  			return
		91  		}
		92  
		93  		// remember arguments that have been evaluated already
		94  		alist := []operand{*x}
		95  
		96  		// spec: "As a special case, append also accepts a first argument assignable
		97  		// to type []byte with a second argument of string type followed by ... .
		98  		// This form appends the bytes of the string.
		99  		if nargs == 2 && call.Ellipsis.IsValid() {
	 100  			if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
	 101  				arg(x, 1)
	 102  				if x.mode == invalid {
	 103  					return
	 104  				}
	 105  				if isString(x.typ) {
	 106  					if check.Types != nil {
	 107  						sig := makeSig(S, S, x.typ)
	 108  						sig.variadic = true
	 109  						check.recordBuiltinType(call.Fun, sig)
	 110  					}
	 111  					x.mode = value
	 112  					x.typ = S
	 113  					break
	 114  				}
	 115  				alist = append(alist, *x)
	 116  				// fallthrough
	 117  			}
	 118  		}
	 119  
	 120  		// check general case by creating custom signature
	 121  		sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
	 122  		sig.variadic = true
	 123  		var xlist []*operand
	 124  		// convert []operand to []*operand
	 125  		for i := range alist {
	 126  			xlist = append(xlist, &alist[i])
	 127  		}
	 128  		for i := len(alist); i < nargs; i++ {
	 129  			var x operand
	 130  			arg(&x, i)
	 131  			xlist = append(xlist, &x)
	 132  		}
	 133  		check.arguments(call, sig, nil, xlist) // discard result (we know the result type)
	 134  		// ok to continue even if check.arguments reported errors
	 135  
	 136  		x.mode = value
	 137  		x.typ = S
	 138  		if check.Types != nil {
	 139  			check.recordBuiltinType(call.Fun, sig)
	 140  		}
	 141  
	 142  	case _Cap, _Len:
	 143  		// cap(x)
	 144  		// len(x)
	 145  		mode := invalid
	 146  		var typ Type
	 147  		var val constant.Value
	 148  		switch typ = implicitArrayDeref(optype(x.typ)); t := typ.(type) {
	 149  		case *Basic:
	 150  			if isString(t) && id == _Len {
	 151  				if x.mode == constant_ {
	 152  					mode = constant_
	 153  					val = constant.MakeInt64(int64(len(constant.StringVal(x.val))))
	 154  				} else {
	 155  					mode = value
	 156  				}
	 157  			}
	 158  
	 159  		case *Array:
	 160  			mode = value
	 161  			// spec: "The expressions len(s) and cap(s) are constants
	 162  			// if the type of s is an array or pointer to an array and
	 163  			// the expression s does not contain channel receives or
	 164  			// function calls; in this case s is not evaluated."
	 165  			if !check.hasCallOrRecv {
	 166  				mode = constant_
	 167  				if t.len >= 0 {
	 168  					val = constant.MakeInt64(t.len)
	 169  				} else {
	 170  					val = constant.MakeUnknown()
	 171  				}
	 172  			}
	 173  
	 174  		case *Slice, *Chan:
	 175  			mode = value
	 176  
	 177  		case *Map:
	 178  			if id == _Len {
	 179  				mode = value
	 180  			}
	 181  
	 182  		case *_Sum:
	 183  			if t.is(func(t Type) bool {
	 184  				switch t := under(t).(type) {
	 185  				case *Basic:
	 186  					if isString(t) && id == _Len {
	 187  						return true
	 188  					}
	 189  				case *Array, *Slice, *Chan:
	 190  					return true
	 191  				case *Map:
	 192  					if id == _Len {
	 193  						return true
	 194  					}
	 195  				}
	 196  				return false
	 197  			}) {
	 198  				mode = value
	 199  			}
	 200  		}
	 201  
	 202  		if mode == invalid && typ != Typ[Invalid] {
	 203  			code := _InvalidCap
	 204  			if id == _Len {
	 205  				code = _InvalidLen
	 206  			}
	 207  			check.invalidArg(x, code, "%s for %s", x, bin.name)
	 208  			return
	 209  		}
	 210  
	 211  		x.mode = mode
	 212  		x.typ = Typ[Int]
	 213  		x.val = val
	 214  		if check.Types != nil && mode != constant_ {
	 215  			check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
	 216  		}
	 217  
	 218  	case _Close:
	 219  		// close(c)
	 220  		c := asChan(x.typ)
	 221  		if c == nil {
	 222  			check.invalidArg(x, _InvalidClose, "%s is not a channel", x)
	 223  			return
	 224  		}
	 225  		if c.dir == RecvOnly {
	 226  			check.invalidArg(x, _InvalidClose, "%s must not be a receive-only channel", x)
	 227  			return
	 228  		}
	 229  
	 230  		x.mode = novalue
	 231  		if check.Types != nil {
	 232  			check.recordBuiltinType(call.Fun, makeSig(nil, c))
	 233  		}
	 234  
	 235  	case _Complex:
	 236  		// complex(x, y floatT) complexT
	 237  		var y operand
	 238  		arg(&y, 1)
	 239  		if y.mode == invalid {
	 240  			return
	 241  		}
	 242  
	 243  		// convert or check untyped arguments
	 244  		d := 0
	 245  		if isUntyped(x.typ) {
	 246  			d |= 1
	 247  		}
	 248  		if isUntyped(y.typ) {
	 249  			d |= 2
	 250  		}
	 251  		switch d {
	 252  		case 0:
	 253  			// x and y are typed => nothing to do
	 254  		case 1:
	 255  			// only x is untyped => convert to type of y
	 256  			check.convertUntyped(x, y.typ)
	 257  		case 2:
	 258  			// only y is untyped => convert to type of x
	 259  			check.convertUntyped(&y, x.typ)
	 260  		case 3:
	 261  			// x and y are untyped =>
	 262  			// 1) if both are constants, convert them to untyped
	 263  			//		floating-point numbers if possible,
	 264  			// 2) if one of them is not constant (possible because
	 265  			//		it contains a shift that is yet untyped), convert
	 266  			//		both of them to float64 since they must have the
	 267  			//		same type to succeed (this will result in an error
	 268  			//		because shifts of floats are not permitted)
	 269  			if x.mode == constant_ && y.mode == constant_ {
	 270  				toFloat := func(x *operand) {
	 271  					if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
	 272  						x.typ = Typ[UntypedFloat]
	 273  					}
	 274  				}
	 275  				toFloat(x)
	 276  				toFloat(&y)
	 277  			} else {
	 278  				check.convertUntyped(x, Typ[Float64])
	 279  				check.convertUntyped(&y, Typ[Float64])
	 280  				// x and y should be invalid now, but be conservative
	 281  				// and check below
	 282  			}
	 283  		}
	 284  		if x.mode == invalid || y.mode == invalid {
	 285  			return
	 286  		}
	 287  
	 288  		// both argument types must be identical
	 289  		if !check.identical(x.typ, y.typ) {
	 290  			check.invalidArg(x, _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ)
	 291  			return
	 292  		}
	 293  
	 294  		// the argument types must be of floating-point type
	 295  		f := func(x Type) Type {
	 296  			if t := asBasic(x); t != nil {
	 297  				switch t.kind {
	 298  				case Float32:
	 299  					return Typ[Complex64]
	 300  				case Float64:
	 301  					return Typ[Complex128]
	 302  				case UntypedFloat:
	 303  					return Typ[UntypedComplex]
	 304  				}
	 305  			}
	 306  			return nil
	 307  		}
	 308  		resTyp := check.applyTypeFunc(f, x.typ)
	 309  		if resTyp == nil {
	 310  			check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ)
	 311  			return
	 312  		}
	 313  
	 314  		// if both arguments are constants, the result is a constant
	 315  		if x.mode == constant_ && y.mode == constant_ {
	 316  			x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
	 317  		} else {
	 318  			x.mode = value
	 319  		}
	 320  
	 321  		if check.Types != nil && x.mode != constant_ {
	 322  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
	 323  		}
	 324  
	 325  		x.typ = resTyp
	 326  
	 327  	case _Copy:
	 328  		// copy(x, y []T) int
	 329  		var dst Type
	 330  		if t := asSlice(x.typ); t != nil {
	 331  			dst = t.elem
	 332  		}
	 333  
	 334  		var y operand
	 335  		arg(&y, 1)
	 336  		if y.mode == invalid {
	 337  			return
	 338  		}
	 339  		var src Type
	 340  		switch t := optype(y.typ).(type) {
	 341  		case *Basic:
	 342  			if isString(y.typ) {
	 343  				src = universeByte
	 344  			}
	 345  		case *Slice:
	 346  			src = t.elem
	 347  		}
	 348  
	 349  		if dst == nil || src == nil {
	 350  			check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y)
	 351  			return
	 352  		}
	 353  
	 354  		if !check.identical(dst, src) {
	 355  			check.invalidArg(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
	 356  			return
	 357  		}
	 358  
	 359  		if check.Types != nil {
	 360  			check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
	 361  		}
	 362  		x.mode = value
	 363  		x.typ = Typ[Int]
	 364  
	 365  	case _Delete:
	 366  		// delete(m, k)
	 367  		m := asMap(x.typ)
	 368  		if m == nil {
	 369  			check.invalidArg(x, _InvalidDelete, "%s is not a map", x)
	 370  			return
	 371  		}
	 372  		arg(x, 1) // k
	 373  		if x.mode == invalid {
	 374  			return
	 375  		}
	 376  
	 377  		check.assignment(x, m.key, "argument to delete")
	 378  		if x.mode == invalid {
	 379  			return
	 380  		}
	 381  
	 382  		x.mode = novalue
	 383  		if check.Types != nil {
	 384  			check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key))
	 385  		}
	 386  
	 387  	case _Imag, _Real:
	 388  		// imag(complexT) floatT
	 389  		// real(complexT) floatT
	 390  
	 391  		// convert or check untyped argument
	 392  		if isUntyped(x.typ) {
	 393  			if x.mode == constant_ {
	 394  				// an untyped constant number can always be considered
	 395  				// as a complex constant
	 396  				if isNumeric(x.typ) {
	 397  					x.typ = Typ[UntypedComplex]
	 398  				}
	 399  			} else {
	 400  				// an untyped non-constant argument may appear if
	 401  				// it contains a (yet untyped non-constant) shift
	 402  				// expression: convert it to complex128 which will
	 403  				// result in an error (shift of complex value)
	 404  				check.convertUntyped(x, Typ[Complex128])
	 405  				// x should be invalid now, but be conservative and check
	 406  				if x.mode == invalid {
	 407  					return
	 408  				}
	 409  			}
	 410  		}
	 411  
	 412  		// the argument must be of complex type
	 413  		f := func(x Type) Type {
	 414  			if t := asBasic(x); t != nil {
	 415  				switch t.kind {
	 416  				case Complex64:
	 417  					return Typ[Float32]
	 418  				case Complex128:
	 419  					return Typ[Float64]
	 420  				case UntypedComplex:
	 421  					return Typ[UntypedFloat]
	 422  				}
	 423  			}
	 424  			return nil
	 425  		}
	 426  		resTyp := check.applyTypeFunc(f, x.typ)
	 427  		if resTyp == nil {
	 428  			code := _InvalidImag
	 429  			if id == _Real {
	 430  				code = _InvalidReal
	 431  			}
	 432  			check.invalidArg(x, code, "argument has type %s, expected complex type", x.typ)
	 433  			return
	 434  		}
	 435  
	 436  		// if the argument is a constant, the result is a constant
	 437  		if x.mode == constant_ {
	 438  			if id == _Real {
	 439  				x.val = constant.Real(x.val)
	 440  			} else {
	 441  				x.val = constant.Imag(x.val)
	 442  			}
	 443  		} else {
	 444  			x.mode = value
	 445  		}
	 446  
	 447  		if check.Types != nil && x.mode != constant_ {
	 448  			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
	 449  		}
	 450  
	 451  		x.typ = resTyp
	 452  
	 453  	case _Make:
	 454  		// make(T, n)
	 455  		// make(T, n, m)
	 456  		// (no argument evaluated yet)
	 457  		arg0 := call.Args[0]
	 458  		T := check.varType(arg0)
	 459  		if T == Typ[Invalid] {
	 460  			return
	 461  		}
	 462  
	 463  		min, max := -1, 10
	 464  		var valid func(t Type) bool
	 465  		valid = func(t Type) bool {
	 466  			var m int
	 467  			switch t := optype(t).(type) {
	 468  			case *Slice:
	 469  				m = 2
	 470  			case *Map, *Chan:
	 471  				m = 1
	 472  			case *_Sum:
	 473  				return t.is(valid)
	 474  			default:
	 475  				return false
	 476  			}
	 477  			if m > min {
	 478  				min = m
	 479  			}
	 480  			if m+1 < max {
	 481  				max = m + 1
	 482  			}
	 483  			return true
	 484  		}
	 485  
	 486  		if !valid(T) {
	 487  			check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)
	 488  			return
	 489  		}
	 490  		if nargs < min || max < nargs {
	 491  			if min == max {
	 492  				check.errorf(call, _WrongArgCount, "%v expects %d arguments; found %d", call, min, nargs)
	 493  			} else {
	 494  				check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, max, nargs)
	 495  			}
	 496  			return
	 497  		}
	 498  
	 499  		types := []Type{T}
	 500  		var sizes []int64 // constant integer arguments, if any
	 501  		for _, arg := range call.Args[1:] {
	 502  			typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
	 503  			types = append(types, typ)
	 504  			if size >= 0 {
	 505  				sizes = append(sizes, size)
	 506  			}
	 507  		}
	 508  		if len(sizes) == 2 && sizes[0] > sizes[1] {
	 509  			check.invalidArg(call.Args[1], _SwappedMakeArgs, "length and capacity swapped")
	 510  			// safe to continue
	 511  		}
	 512  		x.mode = value
	 513  		x.typ = T
	 514  		if check.Types != nil {
	 515  			check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
	 516  		}
	 517  
	 518  	case _New:
	 519  		// new(T)
	 520  		// (no argument evaluated yet)
	 521  		T := check.varType(call.Args[0])
	 522  		if T == Typ[Invalid] {
	 523  			return
	 524  		}
	 525  
	 526  		x.mode = value
	 527  		x.typ = &Pointer{base: T}
	 528  		if check.Types != nil {
	 529  			check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
	 530  		}
	 531  
	 532  	case _Panic:
	 533  		// panic(x)
	 534  		// record panic call if inside a function with result parameters
	 535  		// (for use in Checker.isTerminating)
	 536  		if check.sig != nil && check.sig.results.Len() > 0 {
	 537  			// function has result parameters
	 538  			p := check.isPanic
	 539  			if p == nil {
	 540  				// allocate lazily
	 541  				p = make(map[*ast.CallExpr]bool)
	 542  				check.isPanic = p
	 543  			}
	 544  			p[call] = true
	 545  		}
	 546  
	 547  		check.assignment(x, &emptyInterface, "argument to panic")
	 548  		if x.mode == invalid {
	 549  			return
	 550  		}
	 551  
	 552  		x.mode = novalue
	 553  		if check.Types != nil {
	 554  			check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
	 555  		}
	 556  
	 557  	case _Print, _Println:
	 558  		// print(x, y, ...)
	 559  		// println(x, y, ...)
	 560  		var params []Type
	 561  		if nargs > 0 {
	 562  			params = make([]Type, nargs)
	 563  			for i := 0; i < nargs; i++ {
	 564  				if i > 0 {
	 565  					arg(x, i) // first argument already evaluated
	 566  				}
	 567  				check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name)
	 568  				if x.mode == invalid {
	 569  					// TODO(gri) "use" all arguments?
	 570  					return
	 571  				}
	 572  				params[i] = x.typ
	 573  			}
	 574  		}
	 575  
	 576  		x.mode = novalue
	 577  		if check.Types != nil {
	 578  			check.recordBuiltinType(call.Fun, makeSig(nil, params...))
	 579  		}
	 580  
	 581  	case _Recover:
	 582  		// recover() interface{}
	 583  		x.mode = value
	 584  		x.typ = &emptyInterface
	 585  		if check.Types != nil {
	 586  			check.recordBuiltinType(call.Fun, makeSig(x.typ))
	 587  		}
	 588  
	 589  	case _Add:
	 590  		// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
	 591  		if !check.allowVersion(check.pkg, 1, 17) {
	 592  			check.errorf(call.Fun, _InvalidUnsafeAdd, "unsafe.Add requires go1.17 or later")
	 593  			return
	 594  		}
	 595  
	 596  		check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
	 597  		if x.mode == invalid {
	 598  			return
	 599  		}
	 600  
	 601  		var y operand
	 602  		arg(&y, 1)
	 603  		if !check.isValidIndex(&y, _InvalidUnsafeAdd, "length", true) {
	 604  			return
	 605  		}
	 606  
	 607  		x.mode = value
	 608  		x.typ = Typ[UnsafePointer]
	 609  		if check.Types != nil {
	 610  			check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
	 611  		}
	 612  
	 613  	case _Alignof:
	 614  		// unsafe.Alignof(x T) uintptr
	 615  		if asTypeParam(x.typ) != nil {
	 616  			check.invalidOp(call, _Todo, "unsafe.Alignof undefined for %s", x)
	 617  			return
	 618  		}
	 619  		check.assignment(x, nil, "argument to unsafe.Alignof")
	 620  		if x.mode == invalid {
	 621  			return
	 622  		}
	 623  
	 624  		x.mode = constant_
	 625  		x.val = constant.MakeInt64(check.conf.alignof(x.typ))
	 626  		x.typ = Typ[Uintptr]
	 627  		// result is constant - no need to record signature
	 628  
	 629  	case _Offsetof:
	 630  		// unsafe.Offsetof(x T) uintptr, where x must be a selector
	 631  		// (no argument evaluated yet)
	 632  		arg0 := call.Args[0]
	 633  		selx, _ := unparen(arg0).(*ast.SelectorExpr)
	 634  		if selx == nil {
	 635  			check.invalidArg(arg0, _BadOffsetofSyntax, "%s is not a selector expression", arg0)
	 636  			check.use(arg0)
	 637  			return
	 638  		}
	 639  
	 640  		check.expr(x, selx.X)
	 641  		if x.mode == invalid {
	 642  			return
	 643  		}
	 644  
	 645  		base := derefStructPtr(x.typ)
	 646  		sel := selx.Sel.Name
	 647  		obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel)
	 648  		switch obj.(type) {
	 649  		case nil:
	 650  			check.invalidArg(x, _MissingFieldOrMethod, "%s has no single field %s", base, sel)
	 651  			return
	 652  		case *Func:
	 653  			// TODO(gri) Using derefStructPtr may result in methods being found
	 654  			// that don't actually exist. An error either way, but the error
	 655  			// message is confusing. See: https://play.golang.org/p/al75v23kUy ,
	 656  			// but go/types reports: "invalid argument: x.m is a method value".
	 657  			check.invalidArg(arg0, _InvalidOffsetof, "%s is a method value", arg0)
	 658  			return
	 659  		}
	 660  		if indirect {
	 661  			check.invalidArg(x, _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base)
	 662  			return
	 663  		}
	 664  
	 665  		// TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)?
	 666  		check.recordSelection(selx, FieldVal, base, obj, index, false)
	 667  
	 668  		offs := check.conf.offsetof(base, index)
	 669  		x.mode = constant_
	 670  		x.val = constant.MakeInt64(offs)
	 671  		x.typ = Typ[Uintptr]
	 672  		// result is constant - no need to record signature
	 673  
	 674  	case _Sizeof:
	 675  		// unsafe.Sizeof(x T) uintptr
	 676  		if asTypeParam(x.typ) != nil {
	 677  			check.invalidOp(call, _Todo, "unsafe.Sizeof undefined for %s", x)
	 678  			return
	 679  		}
	 680  		check.assignment(x, nil, "argument to unsafe.Sizeof")
	 681  		if x.mode == invalid {
	 682  			return
	 683  		}
	 684  
	 685  		x.mode = constant_
	 686  		x.val = constant.MakeInt64(check.conf.sizeof(x.typ))
	 687  		x.typ = Typ[Uintptr]
	 688  		// result is constant - no need to record signature
	 689  
	 690  	case _Slice:
	 691  		// unsafe.Slice(ptr *T, len IntegerType) []T
	 692  		if !check.allowVersion(check.pkg, 1, 17) {
	 693  			check.errorf(call.Fun, _InvalidUnsafeSlice, "unsafe.Slice requires go1.17 or later")
	 694  			return
	 695  		}
	 696  
	 697  		typ := asPointer(x.typ)
	 698  		if typ == nil {
	 699  			check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x)
	 700  			return
	 701  		}
	 702  
	 703  		var y operand
	 704  		arg(&y, 1)
	 705  		if !check.isValidIndex(&y, _InvalidUnsafeSlice, "length", false) {
	 706  			return
	 707  		}
	 708  
	 709  		x.mode = value
	 710  		x.typ = NewSlice(typ.base)
	 711  		if check.Types != nil {
	 712  			check.recordBuiltinType(call.Fun, makeSig(x.typ, typ, y.typ))
	 713  		}
	 714  
	 715  	case _Assert:
	 716  		// assert(pred) causes a typechecker error if pred is false.
	 717  		// The result of assert is the value of pred if there is no error.
	 718  		// Note: assert is only available in self-test mode.
	 719  		if x.mode != constant_ || !isBoolean(x.typ) {
	 720  			check.invalidArg(x, _Test, "%s is not a boolean constant", x)
	 721  			return
	 722  		}
	 723  		if x.val.Kind() != constant.Bool {
	 724  			check.errorf(x, _Test, "internal error: value of %s should be a boolean constant", x)
	 725  			return
	 726  		}
	 727  		if !constant.BoolVal(x.val) {
	 728  			check.errorf(call, _Test, "%v failed", call)
	 729  			// compile-time assertion failure - safe to continue
	 730  		}
	 731  		// result is constant - no need to record signature
	 732  
	 733  	case _Trace:
	 734  		// trace(x, y, z, ...) dumps the positions, expressions, and
	 735  		// values of its arguments. The result of trace is the value
	 736  		// of the first argument.
	 737  		// Note: trace is only available in self-test mode.
	 738  		// (no argument evaluated yet)
	 739  		if nargs == 0 {
	 740  			check.dump("%v: trace() without arguments", call.Pos())
	 741  			x.mode = novalue
	 742  			break
	 743  		}
	 744  		var t operand
	 745  		x1 := x
	 746  		for _, arg := range call.Args {
	 747  			check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
	 748  			check.dump("%v: %s", x1.Pos(), x1)
	 749  			x1 = &t // use incoming x only for first argument
	 750  		}
	 751  		// trace is only available in test mode - no need to record signature
	 752  
	 753  	default:
	 754  		unreachable()
	 755  	}
	 756  
	 757  	return true
	 758  }
	 759  
	 760  // applyTypeFunc applies f to x. If x is a type parameter,
	 761  // the result is a type parameter constrained by an new
	 762  // interface bound. The type bounds for that interface
	 763  // are computed by applying f to each of the type bounds
	 764  // of x. If any of these applications of f return nil,
	 765  // applyTypeFunc returns nil.
	 766  // If x is not a type parameter, the result is f(x).
	 767  func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
	 768  	if tp := asTypeParam(x); tp != nil {
	 769  		// Test if t satisfies the requirements for the argument
	 770  		// type and collect possible result types at the same time.
	 771  		var rtypes []Type
	 772  		if !tp.Bound().is(func(x Type) bool {
	 773  			if r := f(x); r != nil {
	 774  				rtypes = append(rtypes, r)
	 775  				return true
	 776  			}
	 777  			return false
	 778  		}) {
	 779  			return nil
	 780  		}
	 781  
	 782  		// construct a suitable new type parameter
	 783  		tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "<type parameter>", nil)
	 784  		ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
	 785  		tsum := _NewSum(rtypes)
	 786  		ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum}
	 787  
	 788  		return ptyp
	 789  	}
	 790  
	 791  	return f(x)
	 792  }
	 793  
	 794  // makeSig makes a signature for the given argument and result types.
	 795  // Default types are used for untyped arguments, and res may be nil.
	 796  func makeSig(res Type, args ...Type) *Signature {
	 797  	list := make([]*Var, len(args))
	 798  	for i, param := range args {
	 799  		list[i] = NewVar(token.NoPos, nil, "", Default(param))
	 800  	}
	 801  	params := NewTuple(list...)
	 802  	var result *Tuple
	 803  	if res != nil {
	 804  		assert(!isUntyped(res))
	 805  		result = NewTuple(NewVar(token.NoPos, nil, "", res))
	 806  	}
	 807  	return &Signature{params: params, results: result}
	 808  }
	 809  
	 810  // implicitArrayDeref returns A if typ is of the form *A and A is an array;
	 811  // otherwise it returns typ.
	 812  //
	 813  func implicitArrayDeref(typ Type) Type {
	 814  	if p, ok := typ.(*Pointer); ok {
	 815  		if a := asArray(p.base); a != nil {
	 816  			return a
	 817  		}
	 818  	}
	 819  	return typ
	 820  }
	 821  
	 822  // unparen returns e with any enclosing parentheses stripped.
	 823  func unparen(e ast.Expr) ast.Expr {
	 824  	for {
	 825  		p, ok := e.(*ast.ParenExpr)
	 826  		if !ok {
	 827  			return e
	 828  		}
	 829  		e = p.X
	 830  	}
	 831  }
	 832  

View as plain text