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 }