github.com/gmemcc/yaegi@v0.12.1-0.20221128122509-aa99124c5d16/internal/cmd/extract/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 "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 unpack because unpack evaluates the 35 // first argument before we even call arg(x, 0)! 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 getter 45 nargs := len(call.Args) 46 switch id { 47 default: 48 // make argument getter 49 arg, nargs, _ = unpack(func(x *operand, i int) { check.multiExpr(x, call.Args[i]) }, nargs, false) 50 if arg == nil { 51 return 52 } 53 // evaluate first argument, if present 54 if nargs > 0 { 55 arg(x, 0) 56 if x.mode == invalid { 57 return 58 } 59 } 60 case _Make, _New, _Offsetof, _Trace: 61 // arguments require special handling 62 } 63 64 // check argument count 65 { 66 msg := "" 67 if nargs < bin.nargs { 68 msg = "not enough" 69 } else if !bin.variadic && nargs > bin.nargs { 70 msg = "too many" 71 } 72 if msg != "" { 73 check.invalidOp(inNode(call, call.Rparen), _WrongArgCount, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs) 74 return 75 } 76 } 77 78 switch id { 79 case _Append: 80 // append(s S, x ...T) S, where T is the element type of S 81 // spec: "The variadic function append appends zero or more values x to s of type 82 // S, which must be a slice type, and returns the resulting slice, also of type S. 83 // The values x are passed to a parameter of type ...T where T is the element type 84 // of S and the respective parameter passing rules apply." 85 S := x.typ 86 var T Type 87 if s, _ := S.Underlying().(*Slice); s != nil { 88 T = s.elem 89 } else { 90 check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) 91 return 92 } 93 94 // remember arguments that have been evaluated already 95 alist := []operand{*x} 96 97 // spec: "As a special case, append also accepts a first argument assignable 98 // to type []byte with a second argument of string type followed by ... . 99 // This form appends the bytes of the string. 100 if nargs == 2 && call.Ellipsis.IsValid() { 101 if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok { 102 arg(x, 1) 103 if x.mode == invalid { 104 return 105 } 106 if isString(x.typ) { 107 if check.Types != nil { 108 sig := makeSig(S, S, x.typ) 109 sig.variadic = true 110 check.recordBuiltinType(call.Fun, sig) 111 } 112 x.mode = value 113 x.typ = S 114 break 115 } 116 alist = append(alist, *x) 117 // fallthrough 118 } 119 } 120 121 // check general case by creating custom signature 122 sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature 123 sig.variadic = true 124 check.arguments(x, call, sig, func(x *operand, i int) { 125 // only evaluate arguments that have not been evaluated before 126 if i < len(alist) { 127 *x = alist[i] 128 return 129 } 130 arg(x, i) 131 }, nargs) 132 // ok to continue even if check.arguments reported errors 133 134 x.mode = value 135 x.typ = S 136 if check.Types != nil { 137 check.recordBuiltinType(call.Fun, sig) 138 } 139 140 case _Cap, _Len: 141 // cap(x) 142 // len(x) 143 mode := invalid 144 var typ Type 145 var val constant.Value 146 switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) { 147 case *Basic: 148 if isString(t) && id == _Len { 149 if x.mode == constant_ { 150 mode = constant_ 151 val = constant.MakeInt64(int64(len(constant.StringVal(x.val)))) 152 } else { 153 mode = value 154 } 155 } 156 157 case *Array: 158 mode = value 159 // spec: "The expressions len(s) and cap(s) are constants 160 // if the type of s is an array or pointer to an array and 161 // the expression s does not contain channel receives or 162 // function calls; in this case s is not evaluated." 163 if !check.hasCallOrRecv { 164 mode = constant_ 165 if t.len >= 0 { 166 val = constant.MakeInt64(t.len) 167 } else { 168 val = constant.MakeUnknown() 169 } 170 } 171 172 case *Slice, *Chan: 173 mode = value 174 175 case *Map: 176 if id == _Len { 177 mode = value 178 } 179 } 180 181 if mode == invalid && typ != Typ[Invalid] { 182 code := _InvalidCap 183 if id == _Len { 184 code = _InvalidLen 185 } 186 check.invalidArg(x, code, "%s for %s", x, bin.name) 187 return 188 } 189 190 x.mode = mode 191 x.typ = Typ[Int] 192 x.val = val 193 if check.Types != nil && mode != constant_ { 194 check.recordBuiltinType(call.Fun, makeSig(x.typ, typ)) 195 } 196 197 case _Close: 198 // close(c) 199 c, _ := x.typ.Underlying().(*Chan) 200 if c == nil { 201 check.invalidArg(x, _InvalidClose, "%s is not a channel", x) 202 return 203 } 204 if c.dir == RecvOnly { 205 check.invalidArg(x, _InvalidClose, "%s must not be a receive-only channel", x) 206 return 207 } 208 209 x.mode = novalue 210 if check.Types != nil { 211 check.recordBuiltinType(call.Fun, makeSig(nil, c)) 212 } 213 214 case _Complex: 215 // complex(x, y floatT) complexT 216 var y operand 217 arg(&y, 1) 218 if y.mode == invalid { 219 return 220 } 221 222 // convert or check untyped arguments 223 d := 0 224 if isUntyped(x.typ) { 225 d |= 1 226 } 227 if isUntyped(y.typ) { 228 d |= 2 229 } 230 switch d { 231 case 0: 232 // x and y are typed => nothing to do 233 case 1: 234 // only x is untyped => convert to type of y 235 check.convertUntyped(x, y.typ) 236 case 2: 237 // only y is untyped => convert to type of x 238 check.convertUntyped(&y, x.typ) 239 case 3: 240 // x and y are untyped => 241 // 1) if both are constants, convert them to untyped 242 // floating-point numbers if possible, 243 // 2) if one of them is not constant (possible because 244 // it contains a shift that is yet untyped), convert 245 // both of them to float64 since they must have the 246 // same type to succeed (this will result in an error 247 // because shifts of floats are not permitted) 248 if x.mode == constant_ && y.mode == constant_ { 249 toFloat := func(x *operand) { 250 if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 { 251 x.typ = Typ[UntypedFloat] 252 } 253 } 254 toFloat(x) 255 toFloat(&y) 256 } else { 257 check.convertUntyped(x, Typ[Float64]) 258 check.convertUntyped(&y, Typ[Float64]) 259 // x and y should be invalid now, but be conservative 260 // and check below 261 } 262 } 263 if x.mode == invalid || y.mode == invalid { 264 return 265 } 266 267 // both argument types must be identical 268 if !check.identical(x.typ, y.typ) { 269 check.invalidArg(x, _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ) 270 return 271 } 272 273 // the argument types must be of floating-point type 274 if !isFloat(x.typ) { 275 check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ) 276 return 277 } 278 279 // if both arguments are constants, the result is a constant 280 if x.mode == constant_ && y.mode == constant_ { 281 x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val))) 282 } else { 283 x.mode = value 284 } 285 286 // determine result type 287 var res BasicKind 288 switch x.typ.Underlying().(*Basic).kind { 289 case Float32: 290 res = Complex64 291 case Float64: 292 res = Complex128 293 case UntypedFloat: 294 res = UntypedComplex 295 default: 296 unreachable() 297 } 298 resTyp := Typ[res] 299 300 if check.Types != nil && x.mode != constant_ { 301 check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ)) 302 } 303 304 x.typ = resTyp 305 306 case _Copy: 307 // copy(x, y []T) int 308 var dst Type 309 if t, _ := x.typ.Underlying().(*Slice); t != nil { 310 dst = t.elem 311 } 312 313 var y operand 314 arg(&y, 1) 315 if y.mode == invalid { 316 return 317 } 318 var src Type 319 switch t := y.typ.Underlying().(type) { 320 case *Basic: 321 if isString(y.typ) { 322 src = universeByte 323 } 324 case *Slice: 325 src = t.elem 326 } 327 328 if dst == nil || src == nil { 329 check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) 330 return 331 } 332 333 if !check.identical(dst, src) { 334 check.invalidArg(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) 335 return 336 } 337 338 if check.Types != nil { 339 check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ)) 340 } 341 x.mode = value 342 x.typ = Typ[Int] 343 344 case _Delete: 345 // delete(m, k) 346 m, _ := x.typ.Underlying().(*Map) 347 if m == nil { 348 check.invalidArg(x, _InvalidDelete, "%s is not a map", x) 349 return 350 } 351 arg(x, 1) // k 352 if x.mode == invalid { 353 return 354 } 355 356 if ok, code := x.assignableTo(check, m.key, nil); !ok { 357 check.invalidArg(x, code, "%s is not assignable to %s", x, m.key) 358 return 359 } 360 361 x.mode = novalue 362 if check.Types != nil { 363 check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key)) 364 } 365 366 case _Imag, _Real: 367 // imag(complexT) floatT 368 // real(complexT) floatT 369 370 // convert or check untyped argument 371 if isUntyped(x.typ) { 372 if x.mode == constant_ { 373 // an untyped constant number can always be considered 374 // as a complex constant 375 if isNumeric(x.typ) { 376 x.typ = Typ[UntypedComplex] 377 } 378 } else { 379 // an untyped non-constant argument may appear if 380 // it contains a (yet untyped non-constant) shift 381 // expression: convert it to complex128 which will 382 // result in an error (shift of complex value) 383 check.convertUntyped(x, Typ[Complex128]) 384 // x should be invalid now, but be conservative and check 385 if x.mode == invalid { 386 return 387 } 388 } 389 } 390 391 // the argument must be of complex type 392 if !isComplex(x.typ) { 393 code := _InvalidImag 394 if id == _Real { 395 code = _InvalidReal 396 } 397 check.invalidArg(x, code, "argument has type %s, expected complex type", x.typ) 398 return 399 } 400 401 // if the argument is a constant, the result is a constant 402 if x.mode == constant_ { 403 if id == _Real { 404 x.val = constant.Real(x.val) 405 } else { 406 x.val = constant.Imag(x.val) 407 } 408 } else { 409 x.mode = value 410 } 411 412 // determine result type 413 var res BasicKind 414 switch x.typ.Underlying().(*Basic).kind { 415 case Complex64: 416 res = Float32 417 case Complex128: 418 res = Float64 419 case UntypedComplex: 420 res = UntypedFloat 421 default: 422 unreachable() 423 } 424 resTyp := Typ[res] 425 426 if check.Types != nil && x.mode != constant_ { 427 check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ)) 428 } 429 430 x.typ = resTyp 431 432 case _Make: 433 // make(T, n) 434 // make(T, n, m) 435 // (no argument evaluated yet) 436 arg0 := call.Args[0] 437 T := check.typ(arg0) 438 if T == Typ[Invalid] { 439 return 440 } 441 442 var min int // minimum number of arguments 443 switch T.Underlying().(type) { 444 case *Slice: 445 min = 2 446 case *Map, *Chan: 447 min = 1 448 default: 449 check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) 450 return 451 } 452 if nargs < min || min+1 < nargs { 453 check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs) 454 return 455 } 456 types := []Type{T} 457 var sizes []int64 // constant integer arguments, if any 458 for _, arg := range call.Args[1:] { 459 typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid] 460 types = append(types, typ) 461 if size >= 0 { 462 sizes = append(sizes, size) 463 } 464 } 465 if len(sizes) == 2 && sizes[0] > sizes[1] { 466 check.invalidArg(call.Args[1], _SwappedMakeArgs, "length and capacity swapped") 467 // safe to continue 468 } 469 x.mode = value 470 x.typ = T 471 if check.Types != nil { 472 check.recordBuiltinType(call.Fun, makeSig(x.typ, types...)) 473 } 474 475 case _New: 476 // new(T) 477 // (no argument evaluated yet) 478 T := check.typ(call.Args[0]) 479 if T == Typ[Invalid] { 480 return 481 } 482 483 x.mode = value 484 x.typ = &Pointer{base: T} 485 if check.Types != nil { 486 check.recordBuiltinType(call.Fun, makeSig(x.typ, T)) 487 } 488 489 case _Panic: 490 // panic(x) 491 // record panic call if inside a function with result parameters 492 // (for use in Checker.isTerminating) 493 if check.sig != nil && check.sig.results.Len() > 0 { 494 // function has result parameters 495 p := check.isPanic 496 if p == nil { 497 // allocate lazily 498 p = make(map[*ast.CallExpr]bool) 499 check.isPanic = p 500 } 501 p[call] = true 502 } 503 504 check.assignment(x, &emptyInterface, "argument to panic") 505 if x.mode == invalid { 506 return 507 } 508 509 x.mode = novalue 510 if check.Types != nil { 511 check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface)) 512 } 513 514 case _Print, _Println: 515 // print(x, y, ...) 516 // println(x, y, ...) 517 var params []Type 518 if nargs > 0 { 519 params = make([]Type, nargs) 520 for i := 0; i < nargs; i++ { 521 if i > 0 { 522 arg(x, i) // first argument already evaluated 523 } 524 check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name) 525 if x.mode == invalid { 526 // TODO(gri) "use" all arguments? 527 return 528 } 529 params[i] = x.typ 530 } 531 } 532 533 x.mode = novalue 534 if check.Types != nil { 535 check.recordBuiltinType(call.Fun, makeSig(nil, params...)) 536 } 537 538 case _Recover: 539 // recover() interface{} 540 x.mode = value 541 x.typ = &emptyInterface 542 if check.Types != nil { 543 check.recordBuiltinType(call.Fun, makeSig(x.typ)) 544 } 545 546 case _Alignof: 547 // unsafe.Alignof(x T) uintptr 548 check.assignment(x, nil, "argument to unsafe.Alignof") 549 if x.mode == invalid { 550 return 551 } 552 553 x.mode = constant_ 554 x.val = constant.MakeInt64(check.conf.alignof(x.typ)) 555 x.typ = Typ[Uintptr] 556 // result is constant - no need to record signature 557 558 case _Offsetof: 559 // unsafe.Offsetof(x T) uintptr, where x must be a selector 560 // (no argument evaluated yet) 561 arg0 := call.Args[0] 562 selx, _ := unparen(arg0).(*ast.SelectorExpr) 563 if selx == nil { 564 check.invalidArg(arg0, _BadOffsetofSyntax, "%s is not a selector expression", arg0) 565 check.use(arg0) 566 return 567 } 568 569 check.expr(x, selx.X) 570 if x.mode == invalid { 571 return 572 } 573 574 base := derefStructPtr(x.typ) 575 sel := selx.Sel.Name 576 obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel) 577 switch obj.(type) { 578 case nil: 579 check.invalidArg(x, _MissingFieldOrMethod, "%s has no single field %s", base, sel) 580 return 581 case *Func: 582 // TODO(gri) Using derefStructPtr may result in methods being found 583 // that don't actually exist. An error either way, but the error 584 // message is confusing. See: https://play.golang.org/p/al75v23kUy , 585 // but go/types reports: "invalid argument: x.m is a method value". 586 check.invalidArg(arg0, _InvalidOffsetof, "%s is a method value", arg0) 587 return 588 } 589 if indirect { 590 check.invalidArg(x, _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base) 591 return 592 } 593 594 // TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)? 595 check.recordSelection(selx, FieldVal, base, obj, index, false) 596 597 offs := check.conf.offsetof(base, index) 598 x.mode = constant_ 599 x.val = constant.MakeInt64(offs) 600 x.typ = Typ[Uintptr] 601 // result is constant - no need to record signature 602 603 case _Sizeof: 604 // unsafe.Sizeof(x T) uintptr 605 check.assignment(x, nil, "argument to unsafe.Sizeof") 606 if x.mode == invalid { 607 return 608 } 609 610 x.mode = constant_ 611 x.val = constant.MakeInt64(check.conf.sizeof(x.typ)) 612 x.typ = Typ[Uintptr] 613 // result is constant - no need to record signature 614 615 case _Assert: 616 // assert(pred) causes a typechecker error if pred is false. 617 // The result of assert is the value of pred if there is no error. 618 // Note: assert is only available in self-test mode. 619 if x.mode != constant_ || !isBoolean(x.typ) { 620 check.invalidArg(x, _Test, "%s is not a boolean constant", x) 621 return 622 } 623 if x.val.Kind() != constant.Bool { 624 check.errorf(x, _Test, "internal error: value of %s should be a boolean constant", x) 625 return 626 } 627 if !constant.BoolVal(x.val) { 628 check.errorf(call, _Test, "%v failed", call) 629 // compile-time assertion failure - safe to continue 630 } 631 // result is constant - no need to record signature 632 633 case _Trace: 634 // trace(x, y, z, ...) dumps the positions, expressions, and 635 // values of its arguments. The result of trace is the value 636 // of the first argument. 637 // Note: trace is only available in self-test mode. 638 // (no argument evaluated yet) 639 if nargs == 0 { 640 check.dump("%v: trace() without arguments", call.Pos()) 641 x.mode = novalue 642 break 643 } 644 var t operand 645 x1 := x 646 for _, arg := range call.Args { 647 check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T)) 648 check.dump("%v: %s", x1.Pos(), x1) 649 x1 = &t // use incoming x only for first argument 650 } 651 // trace is only available in test mode - no need to record signature 652 653 default: 654 unreachable() 655 } 656 657 return true 658 } 659 660 // makeSig makes a signature for the given argument and result types. 661 // Default types are used for untyped arguments, and res may be nil. 662 func makeSig(res Type, args ...Type) *Signature { 663 list := make([]*Var, len(args)) 664 for i, param := range args { 665 list[i] = NewVar(token.NoPos, nil, "", Default(param)) 666 } 667 params := NewTuple(list...) 668 var result *Tuple 669 if res != nil { 670 assert(!isUntyped(res)) 671 result = NewTuple(NewVar(token.NoPos, nil, "", res)) 672 } 673 return &Signature{params: params, results: result} 674 } 675 676 // implicitArrayDeref returns A if typ is of the form *A and A is an array; 677 // otherwise it returns typ. 678 // 679 func implicitArrayDeref(typ Type) Type { 680 if p, ok := typ.(*Pointer); ok { 681 if a, ok := p.base.Underlying().(*Array); ok { 682 return a 683 } 684 } 685 return typ 686 } 687 688 // unparen returns e with any enclosing parentheses stripped. 689 func unparen(e ast.Expr) ast.Expr { 690 for { 691 p, ok := e.(*ast.ParenExpr) 692 if !ok { 693 return e 694 } 695 e = p.X 696 } 697 }