gitlab.com/ethan.reesor/vscode-notebooks/yaegi@v0.0.0-20220417214422-5c573557938e/interp/typecheck.go (about) 1 package interp 2 3 import ( 4 "errors" 5 "go/constant" 6 "go/token" 7 "math" 8 "reflect" 9 ) 10 11 type opPredicates map[action]func(reflect.Type) bool 12 13 // typecheck handles all type checking following "go/types" logic. 14 // 15 // Due to variant type systems (itype vs reflect.Type) a single 16 // type system should used, namely reflect.Type with exception 17 // of the untyped flag on itype. 18 type typecheck struct { 19 scope *scope 20 } 21 22 // op type checks an expression against a set of expression predicates. 23 func (check typecheck) op(p opPredicates, a action, n, c *node, t reflect.Type) error { 24 if pred := p[a]; pred != nil { 25 if !pred(t) { 26 return n.cfgErrorf("invalid operation: operator %v not defined on %s", n.action, c.typ.id()) 27 } 28 } else { 29 return n.cfgErrorf("invalid operation: unknown operator %v", n.action) 30 } 31 return nil 32 } 33 34 // assignment checks if n can be assigned to typ. 35 // 36 // Use typ == nil to indicate assignment to an untyped blank identifier. 37 func (check typecheck) assignment(n *node, typ *itype, context string) error { 38 if n.typ == nil { 39 return n.cfgErrorf("invalid type in %s", context) 40 } 41 if n.typ.untyped { 42 if typ == nil || isInterface(typ) { 43 if typ == nil && n.typ.cat == nilT { 44 return n.cfgErrorf("use of untyped nil in %s", context) 45 } 46 typ = n.typ.defaultType(n.rval, check.scope) 47 } 48 if err := check.convertUntyped(n, typ); err != nil { 49 return err 50 } 51 } 52 53 if typ == nil { 54 return nil 55 } 56 57 if !n.typ.assignableTo(typ) && typ.str != "*unsafe2.dummy" { 58 if context == "" { 59 return n.cfgErrorf("cannot use type %s as type %s", n.typ.id(), typ.id()) 60 } 61 return n.cfgErrorf("cannot use type %s as type %s in %s", n.typ.id(), typ.id(), context) 62 } 63 return nil 64 } 65 66 // assignExpr type checks an assign expression. 67 // 68 // This is done per pair of assignments. 69 func (check typecheck) assignExpr(n, dest, src *node) error { 70 if n.action == aAssign { 71 isConst := n.anc.kind == constDecl 72 if !isConst { 73 // var operations must be typed 74 dest.typ = dest.typ.defaultType(src.rval, check.scope) 75 } 76 77 return check.assignment(src, dest.typ, "assignment") 78 } 79 80 // assignment operations. 81 if n.nleft > 1 || n.nright > 1 { 82 return n.cfgErrorf("assignment operation %s requires single-valued expressions", n.action) 83 } 84 85 return check.binaryExpr(n) 86 } 87 88 // addressExpr type checks a unary address expression. 89 func (check typecheck) addressExpr(n *node) error { 90 c0 := n.child[0] 91 found := false 92 for !found { 93 switch c0.kind { 94 case parenExpr: 95 c0 = c0.child[0] 96 continue 97 case selectorExpr: 98 c0 = c0.child[1] 99 continue 100 case starExpr: 101 c0 = c0.child[0] 102 continue 103 case indexExpr, sliceExpr: 104 c := c0.child[0] 105 if isArray(c.typ) || isMap(c.typ) { 106 c0 = c 107 found = true 108 continue 109 } 110 case compositeLitExpr, identExpr: 111 found = true 112 continue 113 } 114 return n.cfgErrorf("invalid operation: cannot take address of %s [kind: %s]", c0.typ.id(), kinds[c0.kind]) 115 } 116 return nil 117 } 118 119 // starExpr type checks a star expression on a variable. 120 func (check typecheck) starExpr(n *node) error { 121 if n.typ.TypeOf().Kind() != reflect.Ptr { 122 return n.cfgErrorf("invalid operation: cannot indirect %q", n.name()) 123 } 124 return nil 125 } 126 127 var unaryOpPredicates = opPredicates{ 128 aPos: isNumber, 129 aNeg: isNumber, 130 aBitNot: isInt, 131 aNot: isBoolean, 132 } 133 134 // unaryExpr type checks a unary expression. 135 func (check typecheck) unaryExpr(n *node) error { 136 c0 := n.child[0] 137 t0 := c0.typ.TypeOf() 138 139 if n.action == aRecv { 140 if !isChan(c0.typ) { 141 return n.cfgErrorf("invalid operation: cannot receive from non-channel %s", c0.typ.id()) 142 } 143 if isSendChan(c0.typ) { 144 return n.cfgErrorf("invalid operation: cannot receive from send-only channel %s", c0.typ.id()) 145 } 146 return nil 147 } 148 149 return check.op(unaryOpPredicates, n.action, n, c0, t0) 150 } 151 152 // shift type checks a shift binary expression. 153 func (check typecheck) shift(n *node) error { 154 c0, c1 := n.child[0], n.child[1] 155 t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf() 156 157 var v0 constant.Value 158 if c0.typ.untyped && c0.rval.IsValid() { 159 v0 = constant.ToInt(c0.rval.Interface().(constant.Value)) 160 c0.rval = reflect.ValueOf(v0) 161 } 162 163 if !(c0.typ.untyped && v0 != nil && v0.Kind() == constant.Int || isInt(t0)) { 164 return n.cfgErrorf("invalid operation: shift of type %v", c0.typ.id()) 165 } 166 167 switch { 168 case c1.typ.untyped: 169 if err := check.convertUntyped(c1, check.scope.getType("uint")); err != nil { 170 return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id()) 171 } 172 case isInt(t1): 173 // nothing to do 174 default: 175 return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id()) 176 } 177 return nil 178 } 179 180 // comparison type checks a comparison binary expression. 181 func (check typecheck) comparison(n *node) error { 182 c0, c1 := n.child[0], n.child[1] 183 184 if !c0.typ.assignableTo(c1.typ) && !c1.typ.assignableTo(c0.typ) { 185 return n.cfgErrorf("invalid operation: mismatched types %s and %s", c0.typ.id(), c1.typ.id()) 186 } 187 188 ok := false 189 switch n.action { 190 case aEqual, aNotEqual: 191 ok = c0.typ.comparable() && c1.typ.comparable() || c0.typ.isNil() && c1.typ.hasNil() || c1.typ.isNil() && c0.typ.hasNil() 192 case aLower, aLowerEqual, aGreater, aGreaterEqual: 193 ok = c0.typ.ordered() && c1.typ.ordered() 194 } 195 if !ok { 196 typ := c0.typ 197 if typ.isNil() { 198 typ = c1.typ 199 } 200 return n.cfgErrorf("invalid operation: operator %v not defined on %s", n.action, typ.id(), ".") 201 } 202 return nil 203 } 204 205 var binaryOpPredicates = opPredicates{ 206 aAdd: func(typ reflect.Type) bool { return isNumber(typ) || isString(typ) }, 207 aSub: isNumber, 208 aMul: isNumber, 209 aQuo: isNumber, 210 aRem: isInt, 211 212 aAnd: isInt, 213 aOr: isInt, 214 aXor: isInt, 215 aAndNot: isInt, 216 217 aLand: isBoolean, 218 aLor: isBoolean, 219 } 220 221 // binaryExpr type checks a binary expression. 222 func (check typecheck) binaryExpr(n *node) error { 223 c0, c1 := n.child[0], n.child[1] 224 225 a := n.action 226 if isAssignAction(a) { 227 a-- 228 } 229 230 if isShiftAction(a) { 231 return check.shift(n) 232 } 233 234 switch n.action { 235 case aAdd: 236 if n.typ == nil { 237 break 238 } 239 // Catch mixing string and number for "+" operator use. 240 k, k0, k1 := isNumber(n.typ.TypeOf()), isNumber(c0.typ.TypeOf()), isNumber(c1.typ.TypeOf()) 241 if k != k0 || k != k1 { 242 return n.cfgErrorf("cannot use type %s as type %s in assignment", c0.typ.id(), n.typ.id()) 243 } 244 case aRem: 245 if zeroConst(c1) { 246 return n.cfgErrorf("invalid operation: division by zero") 247 } 248 case aQuo: 249 if zeroConst(c1) { 250 return n.cfgErrorf("invalid operation: division by zero") 251 } 252 if c0.rval.IsValid() && c1.rval.IsValid() { 253 // Avoid constant conversions below to ensure correct constant integer quotient. 254 return nil 255 } 256 } 257 258 _ = check.convertUntyped(c0, c1.typ) 259 _ = check.convertUntyped(c1, c0.typ) 260 261 if isComparisonAction(a) { 262 return check.comparison(n) 263 } 264 265 if !c0.typ.equals(c1.typ) { 266 return n.cfgErrorf("invalid operation: mismatched types %s and %s", c0.typ.id(), c1.typ.id()) 267 } 268 269 t0 := c0.typ.TypeOf() 270 271 return check.op(binaryOpPredicates, a, n, c0, t0) 272 } 273 274 func zeroConst(n *node) bool { 275 return n.typ.untyped && constant.Sign(n.rval.Interface().(constant.Value)) == 0 276 } 277 278 func (check typecheck) index(n *node, max int) error { 279 if err := check.convertUntyped(n, check.scope.getType("int")); err != nil { 280 return err 281 } 282 283 if !isInt(n.typ.TypeOf()) { 284 return n.cfgErrorf("index %s must be integer", n.typ.id()) 285 } 286 287 if !n.rval.IsValid() || max < 1 { 288 return nil 289 } 290 291 if int(vInt(n.rval)) >= max { 292 return n.cfgErrorf("index %s is out of bounds", n.typ.id()) 293 } 294 295 return nil 296 } 297 298 // arrayLitExpr type checks an array composite literal expression. 299 func (check typecheck) arrayLitExpr(child []*node, typ *itype) error { 300 cat := typ.cat 301 length := typ.length 302 typ = typ.val 303 visited := make(map[int]bool, len(child)) 304 index := 0 305 for _, c := range child { 306 n := c 307 switch { 308 case c.kind == keyValueExpr: 309 if err := check.index(c.child[0], length); err != nil { 310 return c.cfgErrorf("index %s must be integer constant", c.child[0].typ.id()) 311 } 312 n = c.child[1] 313 index = int(vInt(c.child[0].rval)) 314 case cat == arrayT && index >= length: 315 return c.cfgErrorf("index %d is out of bounds (>= %d)", index, length) 316 } 317 318 if visited[index] { 319 return n.cfgErrorf("duplicate index %d in array or slice literal", index) 320 } 321 visited[index] = true 322 index++ 323 324 if err := check.assignment(n, typ, "array or slice literal"); err != nil { 325 return err 326 } 327 } 328 return nil 329 } 330 331 // mapLitExpr type checks an map composite literal expression. 332 func (check typecheck) mapLitExpr(child []*node, ktyp, vtyp *itype) error { 333 visited := make(map[interface{}]bool, len(child)) 334 for _, c := range child { 335 if c.kind != keyValueExpr { 336 return c.cfgErrorf("missing key in map literal") 337 } 338 339 key, val := c.child[0], c.child[1] 340 if err := check.assignment(key, ktyp, "map literal"); err != nil { 341 return err 342 } 343 344 if key.rval.IsValid() { 345 kval := key.rval.Interface() 346 if visited[kval] { 347 return c.cfgErrorf("duplicate key %s in map literal", kval) 348 } 349 visited[kval] = true 350 } 351 352 if err := check.assignment(val, vtyp, "map literal"); err != nil { 353 return err 354 } 355 } 356 return nil 357 } 358 359 // structLitExpr type checks a struct composite literal expression. 360 func (check typecheck) structLitExpr(child []*node, typ *itype) error { 361 if len(child) == 0 { 362 return nil 363 } 364 365 if child[0].kind == keyValueExpr { 366 // All children must be keyValueExpr 367 visited := make([]bool, len(typ.field)) 368 for _, c := range child { 369 if c.kind != keyValueExpr { 370 return c.cfgErrorf("mixture of field:value and value elements in struct literal") 371 } 372 373 key, val := c.child[0], c.child[1] 374 name := key.ident 375 if name == "" { 376 return c.cfgErrorf("invalid field name %s in struct literal", key.typ.id()) 377 } 378 i := typ.fieldIndex(name) 379 if i < 0 { 380 return c.cfgErrorf("unknown field %s in struct literal", name) 381 } 382 field := typ.field[i] 383 384 if err := check.assignment(val, field.typ, "struct literal"); err != nil { 385 return err 386 } 387 388 if visited[i] { 389 return c.cfgErrorf("duplicate field name %s in struct literal", name) 390 } 391 visited[i] = true 392 } 393 return nil 394 } 395 396 // No children can be keyValueExpr 397 for i, c := range child { 398 if c.kind == keyValueExpr { 399 return c.cfgErrorf("mixture of field:value and value elements in struct literal") 400 } 401 402 if i >= len(typ.field) { 403 return c.cfgErrorf("too many values in struct literal") 404 } 405 field := typ.field[i] 406 // TODO(nick): check if this field is not exported and in a different package. 407 408 if err := check.assignment(c, field.typ, "struct literal"); err != nil { 409 return err 410 } 411 } 412 if len(child) < len(typ.field) { 413 return child[len(child)-1].cfgErrorf("too few values in struct literal") 414 } 415 return nil 416 } 417 418 // structBinLitExpr type checks a struct composite literal expression on a binary type. 419 func (check typecheck) structBinLitExpr(child []*node, typ reflect.Type) error { 420 if len(child) == 0 { 421 return nil 422 } 423 424 if child[0].kind == keyValueExpr { 425 // All children must be keyValueExpr 426 visited := make(map[string]bool, typ.NumField()) 427 for _, c := range child { 428 if c.kind != keyValueExpr { 429 return c.cfgErrorf("mixture of field:value and value elements in struct literal") 430 } 431 432 key, val := c.child[0], c.child[1] 433 name := key.ident 434 if name == "" { 435 return c.cfgErrorf("invalid field name %s in struct literal", key.typ.id()) 436 } 437 field, ok := typ.FieldByName(name) 438 if !ok { 439 return c.cfgErrorf("unknown field %s in struct literal", name) 440 } 441 442 if err := check.assignment(val, valueTOf(field.Type), "struct literal"); err != nil { 443 return err 444 } 445 446 if visited[field.Name] { 447 return c.cfgErrorf("duplicate field name %s in struct literal", name) 448 } 449 visited[field.Name] = true 450 } 451 return nil 452 } 453 454 // No children can be keyValueExpr 455 for i, c := range child { 456 if c.kind == keyValueExpr { 457 return c.cfgErrorf("mixture of field:value and value elements in struct literal") 458 } 459 460 if i >= typ.NumField() { 461 return c.cfgErrorf("too many values in struct literal") 462 } 463 field := typ.Field(i) 464 if !canExport(field.Name) { 465 return c.cfgErrorf("implicit assignment to unexported field %s in %s literal", field.Name, typ) 466 } 467 468 if err := check.assignment(c, valueTOf(field.Type), "struct literal"); err != nil { 469 return err 470 } 471 } 472 if len(child) < typ.NumField() { 473 return child[len(child)-1].cfgErrorf("too few values in struct literal") 474 } 475 return nil 476 } 477 478 // sliceExpr type checks a slice expression. 479 func (check typecheck) sliceExpr(n *node) error { 480 c, child := n.child[0], n.child[1:] 481 482 t := c.typ.TypeOf() 483 var low, high, max *node 484 if len(child) >= 1 { 485 if n.action == aSlice { 486 low = child[0] 487 } else { 488 high = child[0] 489 } 490 } 491 if len(child) >= 2 { 492 if n.action == aSlice { 493 high = child[1] 494 } else { 495 max = child[1] 496 } 497 } 498 if len(child) == 3 && n.action == aSlice { 499 max = child[2] 500 } 501 502 l := -1 503 valid := false 504 switch t.Kind() { 505 case reflect.String: 506 valid = true 507 if c.rval.IsValid() { 508 l = len(vString(c.rval)) 509 } 510 if max != nil { 511 return max.cfgErrorf("invalid operation: 3-index slice of string") 512 } 513 case reflect.Array: 514 valid = true 515 l = t.Len() 516 // TODO(marc): check addressable status of array object (i.e. composite arrays are not). 517 case reflect.Slice: 518 valid = true 519 case reflect.Ptr: 520 if t.Elem().Kind() == reflect.Array { 521 valid = true 522 l = t.Elem().Len() 523 } 524 } 525 if !valid { 526 return c.cfgErrorf("cannot slice type %s", c.typ.id()) 527 } 528 529 var ind [3]int64 530 for i, nod := range []*node{low, high, max} { 531 x := int64(-1) 532 switch { 533 case nod != nil: 534 max := -1 535 if l >= 0 { 536 max = l + 1 537 } 538 if err := check.index(nod, max); err != nil { 539 return err 540 } 541 if nod.rval.IsValid() { 542 x = vInt(nod.rval) 543 } 544 case i == 0: 545 x = 0 546 case l >= 0: 547 x = int64(l) 548 } 549 ind[i] = x 550 } 551 552 for i, x := range ind[:len(ind)-1] { 553 if x <= 0 { 554 continue 555 } 556 for _, y := range ind[i+1:] { 557 if y < 0 || x <= y { 558 continue 559 } 560 return n.cfgErrorf("invalid index values, must be low <= high <= max") 561 } 562 } 563 return nil 564 } 565 566 // typeAssertionExpr type checks a type assert expression. 567 func (check typecheck) typeAssertionExpr(n *node, typ *itype) error { 568 // TODO(nick): This type check is not complete and should be revisited once 569 // https://github.com/golang/go/issues/39717 lands. It is currently impractical to 570 // type check Named types as they cannot be asserted. 571 572 if n.typ.TypeOf().Kind() != reflect.Interface { 573 return n.cfgErrorf("invalid type assertion: non-interface type %s on left", n.typ.id()) 574 } 575 ims := n.typ.methods() 576 if len(ims) == 0 { 577 // Empty interface must be a dynamic check. 578 return nil 579 } 580 581 if isInterface(typ) { 582 // Asserting to an interface is a dynamic check as we must look to the 583 // underlying struct. 584 return nil 585 } 586 587 for name := range ims { 588 im := lookupFieldOrMethod(n.typ, name) 589 tm := lookupFieldOrMethod(typ, name) 590 if im == nil { 591 // This should not be possible. 592 continue 593 } 594 if tm == nil { 595 // Lookup for non-exported methods is impossible 596 // for bin types, ignore them as they can't be used 597 // directly by the interpreted programs. 598 if !token.IsExported(name) && isBin(typ) { 599 continue 600 } 601 return n.cfgErrorf("impossible type assertion: %s does not implement %s (missing %v method)", typ.id(), n.typ.id(), name) 602 } 603 if tm.recv != nil && tm.recv.TypeOf().Kind() == reflect.Ptr && typ.TypeOf().Kind() != reflect.Ptr { 604 return n.cfgErrorf("impossible type assertion: %s does not implement %s as %q method has a pointer receiver", typ.id(), n.typ.id(), name) 605 } 606 607 err := n.cfgErrorf("impossible type assertion: %s does not implement %s", typ.id(), n.typ.id()) 608 if im.numIn() != tm.numIn() || im.numOut() != tm.numOut() { 609 return err 610 } 611 for i := 0; i < im.numIn(); i++ { 612 if !im.in(i).equals(tm.in(i)) { 613 return err 614 } 615 } 616 for i := 0; i < im.numOut(); i++ { 617 if !im.out(i).equals(tm.out(i)) { 618 return err 619 } 620 } 621 } 622 return nil 623 } 624 625 // conversion type checks the conversion of n to typ. 626 func (check typecheck) conversion(n *node, typ *itype) error { 627 var c constant.Value 628 if n.rval.IsValid() { 629 if con, ok := n.rval.Interface().(constant.Value); ok { 630 c = con 631 } 632 } 633 634 var ok bool 635 switch { 636 case c != nil && isConstType(typ): 637 switch t := typ.TypeOf(); { 638 case representableConst(c, t): 639 ok = true 640 case isInt(n.typ.TypeOf()) && isString(t): 641 codepoint := int64(-1) 642 if i, ok := constant.Int64Val(c); ok { 643 codepoint = i 644 } 645 n.rval = reflect.ValueOf(constant.MakeString(string(rune(codepoint)))) 646 ok = true 647 } 648 649 case n.typ.convertibleTo(typ): 650 ok = true 651 } 652 if !ok { 653 return n.cfgErrorf("cannot convert expression of type %s to type %s", n.typ.id(), typ.id()) 654 } 655 if !n.typ.untyped || c == nil { 656 return nil 657 } 658 if isInterface(typ) || !isConstType(typ) { 659 typ = n.typ.defaultType(n.rval, check.scope) 660 } 661 return check.convertUntyped(n, typ) 662 } 663 664 type param struct { 665 nod *node 666 typ *itype 667 } 668 669 func (p param) Type() *itype { 670 if p.typ != nil { 671 return p.typ 672 } 673 return p.nod.typ 674 } 675 676 // unpackParams unpacks child parameters into a slice of param. 677 // If there is only 1 child and it is a callExpr with an n-value return, 678 // the return types are returned, otherwise the original child nodes are 679 // returned with nil typ. 680 func (check typecheck) unpackParams(child []*node) (params []param) { 681 if len(child) == 1 && isCall(child[0]) && child[0].child[0].typ.numOut() > 1 { 682 c0 := child[0] 683 ftyp := child[0].child[0].typ 684 for i := 0; i < ftyp.numOut(); i++ { 685 params = append(params, param{nod: c0, typ: ftyp.out(i)}) 686 } 687 return params 688 } 689 690 for _, c := range child { 691 params = append(params, param{nod: c}) 692 } 693 return params 694 } 695 696 var builtinFuncs = map[string]struct { 697 args int 698 variadic bool 699 }{ 700 bltnAppend: {args: 1, variadic: true}, 701 bltnCap: {args: 1, variadic: false}, 702 bltnClose: {args: 1, variadic: false}, 703 bltnComplex: {args: 2, variadic: false}, 704 bltnImag: {args: 1, variadic: false}, 705 bltnCopy: {args: 2, variadic: false}, 706 bltnDelete: {args: 2, variadic: false}, 707 bltnLen: {args: 1, variadic: false}, 708 bltnMake: {args: 1, variadic: true}, 709 bltnNew: {args: 1, variadic: false}, 710 bltnPanic: {args: 1, variadic: false}, 711 bltnPrint: {args: 0, variadic: true}, 712 bltnPrintln: {args: 0, variadic: true}, 713 bltnReal: {args: 1, variadic: false}, 714 bltnRecover: {args: 0, variadic: false}, 715 } 716 717 func (check typecheck) builtin(name string, n *node, child []*node, ellipsis bool) error { 718 fun := builtinFuncs[name] 719 if ellipsis && name != bltnAppend { 720 return n.cfgErrorf("invalid use of ... with builtin %s", name) 721 } 722 723 var params []param 724 nparams := len(child) 725 switch name { 726 case bltnMake, bltnNew: 727 // Special param handling 728 default: 729 params = check.unpackParams(child) 730 nparams = len(params) 731 } 732 733 if nparams < fun.args { 734 return n.cfgErrorf("not enough arguments in call to %s", name) 735 } else if !fun.variadic && nparams > fun.args { 736 return n.cfgErrorf("too many arguments for %s", name) 737 } 738 739 switch name { 740 case bltnAppend: 741 typ := params[0].Type() 742 t := typ.TypeOf() 743 if t == nil || t.Kind() != reflect.Slice { 744 return params[0].nod.cfgErrorf("first argument to append must be slice; have %s", typ.id()) 745 } 746 747 if nparams == 1 { 748 return nil 749 } 750 // Special case append([]byte, "test"...) is allowed. 751 t1 := params[1].Type() 752 if nparams == 2 && ellipsis && t.Elem().Kind() == reflect.Uint8 && t1.TypeOf().Kind() == reflect.String { 753 if t1.untyped { 754 return check.convertUntyped(params[1].nod, check.scope.getType("string")) 755 } 756 return nil 757 } 758 759 fun := &node{ 760 typ: &itype{ 761 cat: funcT, 762 arg: []*itype{ 763 typ, 764 {cat: variadicT, val: valueTOf(t.Elem())}, 765 }, 766 ret: []*itype{typ}, 767 }, 768 ident: "append", 769 } 770 return check.arguments(n, child, fun, ellipsis) 771 case bltnCap, bltnLen: 772 typ := arrayDeref(params[0].Type()) 773 ok := false 774 switch typ.TypeOf().Kind() { 775 case reflect.Array, reflect.Slice, reflect.Chan: 776 ok = true 777 case reflect.String, reflect.Map: 778 ok = name == bltnLen 779 } 780 if !ok { 781 return params[0].nod.cfgErrorf("invalid argument for %s", name) 782 } 783 case bltnClose: 784 p := params[0] 785 typ := p.Type() 786 t := typ.TypeOf() 787 if t.Kind() != reflect.Chan { 788 return p.nod.cfgErrorf("invalid operation: non-chan type %s", p.nod.typ.id()) 789 } 790 if t.ChanDir() == reflect.RecvDir { 791 return p.nod.cfgErrorf("invalid operation: cannot close receive-only channel") 792 } 793 case bltnComplex: 794 var err error 795 p0, p1 := params[0], params[1] 796 typ0, typ1 := p0.Type(), p1.Type() 797 switch { 798 case typ0.untyped && !typ1.untyped: 799 err = check.convertUntyped(p0.nod, typ1) 800 case !typ0.untyped && typ1.untyped: 801 err = check.convertUntyped(p1.nod, typ0) 802 case typ0.untyped && typ1.untyped: 803 fltType := check.scope.getType("float64") 804 err = check.convertUntyped(p0.nod, fltType) 805 if err != nil { 806 break 807 } 808 err = check.convertUntyped(p1.nod, fltType) 809 } 810 if err != nil { 811 return err 812 } 813 814 // check we have the correct types after conversion. 815 typ0, typ1 = p0.Type(), p1.Type() 816 if !typ0.equals(typ1) { 817 return n.cfgErrorf("invalid operation: mismatched types %s and %s", typ0.id(), typ1.id()) 818 } 819 if !isFloat(typ0.TypeOf()) { 820 return n.cfgErrorf("invalid operation: arguments have type %s, expected floating-point", typ0.id()) 821 } 822 case bltnImag, bltnReal: 823 p := params[0] 824 typ := p.Type() 825 if typ.untyped { 826 if err := check.convertUntyped(p.nod, check.scope.getType("complex128")); err != nil { 827 return err 828 } 829 } 830 typ = p.Type() 831 if !isComplex(typ.TypeOf()) { 832 return p.nod.cfgErrorf("invalid argument type %s for %s", typ.id(), name) 833 } 834 case bltnCopy: 835 typ0, typ1 := params[0].Type(), params[1].Type() 836 var t0, t1 reflect.Type 837 if t := typ0.TypeOf(); t.Kind() == reflect.Slice { 838 t0 = t.Elem() 839 } 840 841 switch t := typ1.TypeOf(); t.Kind() { 842 case reflect.String: 843 t1 = reflect.TypeOf(byte(1)) 844 case reflect.Slice: 845 t1 = t.Elem() 846 } 847 848 if t0 == nil || t1 == nil { 849 return n.cfgErrorf("copy expects slice arguments") 850 } 851 if !reflect.DeepEqual(t0, t1) { 852 return n.cfgErrorf("arguments to copy have different element types %s and %s", typ0.id(), typ1.id()) 853 } 854 case bltnDelete: 855 typ := params[0].Type() 856 if typ.TypeOf().Kind() != reflect.Map { 857 return params[0].nod.cfgErrorf("first argument to delete must be map; have %s", typ.id()) 858 } 859 ktyp := params[1].Type() 860 if typ.key != nil && !ktyp.assignableTo(typ.key) { 861 return params[1].nod.cfgErrorf("cannot use %s as type %s in delete", ktyp.id(), typ.key.id()) 862 } 863 case bltnMake: 864 var min int 865 switch child[0].typ.TypeOf().Kind() { 866 case reflect.Slice: 867 min = 2 868 case reflect.Map, reflect.Chan: 869 min = 1 870 default: 871 return child[0].cfgErrorf("cannot make %s; type must be slice, map, or channel", child[0].typ.id()) 872 } 873 if nparams < min { 874 return n.cfgErrorf("not enough arguments in call to make") 875 } else if nparams > min+1 { 876 return n.cfgErrorf("too many arguments for make") 877 } 878 879 var sizes []int 880 for _, c := range child[1:] { 881 if err := check.index(c, -1); err != nil { 882 return err 883 } 884 if c.rval.IsValid() { 885 sizes = append(sizes, int(vInt(c.rval))) 886 } 887 } 888 for len(sizes) == 2 && sizes[0] > sizes[1] { 889 return n.cfgErrorf("len larger than cap in make") 890 } 891 892 case bltnPanic: 893 return check.assignment(params[0].nod, check.scope.getType("interface{}"), "argument to panic") 894 case bltnPrint, bltnPrintln: 895 for _, param := range params { 896 if param.typ != nil { 897 continue 898 } 899 900 if err := check.assignment(param.nod, nil, "argument to "+name); err != nil { 901 return err 902 } 903 } 904 case bltnRecover, bltnNew: 905 // Nothing to do. 906 default: 907 return n.cfgErrorf("unsupported builtin %s", name) 908 } 909 return nil 910 } 911 912 // arrayDeref returns A if typ is *A, otherwise typ. 913 func arrayDeref(typ *itype) *itype { 914 if typ.cat == valueT && typ.TypeOf().Kind() == reflect.Ptr { 915 t := typ.TypeOf() 916 if t.Elem().Kind() == reflect.Array { 917 return valueTOf(t.Elem()) 918 } 919 return typ 920 } 921 922 if typ.cat == ptrT && typ.val.cat == arrayT { 923 return typ.val 924 } 925 return typ 926 } 927 928 // arguments type checks the call expression arguments. 929 func (check typecheck) arguments(n *node, child []*node, fun *node, ellipsis bool) error { 930 params := check.unpackParams(child) 931 l := len(child) 932 if ellipsis { 933 if !fun.typ.isVariadic() { 934 return n.cfgErrorf("invalid use of ..., corresponding parameter is non-variadic") 935 } 936 if len(params) > l { 937 return child[0].cfgErrorf("cannot use ... with %d-valued %s", child[0].child[0].typ.numOut(), child[0].child[0].typ.id()) 938 } 939 } 940 941 var cnt int 942 for i, param := range params { 943 ellip := i == l-1 && ellipsis 944 if err := check.argument(param, fun.typ, cnt, l, ellip); err != nil { 945 return err 946 } 947 cnt++ 948 } 949 950 if fun.typ.isVariadic() { 951 cnt++ 952 } 953 if cnt < fun.typ.numIn() { 954 return n.cfgErrorf("not enough arguments in call to %s", fun.name()) 955 } 956 return nil 957 } 958 959 func (check typecheck) argument(p param, ftyp *itype, i, l int, ellipsis bool) error { 960 atyp := getArg(ftyp, i) 961 if atyp == nil { 962 return p.nod.cfgErrorf("too many arguments") 963 } 964 965 if p.typ == nil && isCall(p.nod) && p.nod.child[0].typ.numOut() != 1 { 966 if l == 1 { 967 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp)) 968 } 969 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), atyp.id()) 970 } 971 972 if ellipsis { 973 if i != ftyp.numIn()-1 { 974 return p.nod.cfgErrorf("can only use ... with matching parameter") 975 } 976 t := p.Type().TypeOf() 977 if t.Kind() != reflect.Slice || !(valueTOf(t.Elem())).assignableTo(atyp) { 978 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.typ.id(), (sliceOf(atyp)).id()) 979 } 980 return nil 981 } 982 983 if p.typ != nil { 984 if !p.typ.assignableTo(atyp) { 985 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp)) 986 } 987 return nil 988 } 989 return check.assignment(p.nod, atyp, "") 990 } 991 992 func getArg(ftyp *itype, i int) *itype { 993 l := ftyp.numIn() 994 switch { 995 case ftyp.isVariadic() && i >= l-1: 996 arg := ftyp.in(l - 1).val 997 return arg 998 case i < l: 999 return ftyp.in(i) 1000 case ftyp.cat == valueT && i < ftyp.rtype.NumIn(): 1001 return valueTOf(ftyp.rtype.In(i)) 1002 default: 1003 return nil 1004 } 1005 } 1006 1007 func getArgsID(ftyp *itype) string { 1008 res := "(" 1009 for i, arg := range ftyp.arg { 1010 if i > 0 { 1011 res += "," 1012 } 1013 res += arg.id() 1014 } 1015 res += ")" 1016 return res 1017 } 1018 1019 var errCantConvert = errors.New("cannot convert") 1020 1021 func (check typecheck) convertUntyped(n *node, typ *itype) error { 1022 if n.typ == nil || !n.typ.untyped || typ == nil { 1023 return nil 1024 } 1025 1026 convErr := n.cfgErrorf("cannot convert %s to %s", n.typ.id(), typ.id()) 1027 1028 ntyp, ttyp := n.typ.TypeOf(), typ.TypeOf() 1029 if typ.untyped { 1030 // Both n and target are untyped. 1031 nkind, tkind := ntyp.Kind(), ttyp.Kind() 1032 if isNumber(ntyp) && isNumber(ttyp) { 1033 if nkind < tkind { 1034 n.typ = typ 1035 } 1036 } else if nkind != tkind { 1037 return convErr 1038 } 1039 return nil 1040 } 1041 1042 var ( 1043 ityp *itype 1044 rtyp reflect.Type 1045 err error 1046 ) 1047 switch { 1048 case typ.isNil() && n.typ.isNil(): 1049 n.typ = typ 1050 return nil 1051 case isNumber(ttyp) || isString(ttyp) || isBoolean(ttyp): 1052 ityp = typ 1053 rtyp = ttyp 1054 case isInterface(typ): 1055 if n.typ.isNil() { 1056 return nil 1057 } 1058 if len(n.typ.methods()) > 0 { // untyped cannot be set to iface 1059 return convErr 1060 } 1061 ityp = n.typ.defaultType(n.rval, check.scope) 1062 rtyp = ntyp 1063 case isArray(typ) || isMap(typ) || isChan(typ) || isFunc(typ) || isPtr(typ): 1064 // TODO(nick): above we are acting on itype, but really it is an rtype check. This is not clear which type 1065 // plain we are in. Fix this later. 1066 if !n.typ.isNil() { 1067 return convErr 1068 } 1069 return nil 1070 default: 1071 return convErr 1072 } 1073 1074 if err := check.representable(n, rtyp); err != nil { 1075 return err 1076 } 1077 n.rval, err = check.convertConst(n.rval, rtyp) 1078 if err != nil { 1079 if errors.Is(err, errCantConvert) { 1080 return convErr 1081 } 1082 return n.cfgErrorf(err.Error()) 1083 } 1084 n.typ = ityp 1085 return nil 1086 } 1087 1088 func (check typecheck) representable(n *node, t reflect.Type) error { 1089 if !n.rval.IsValid() { 1090 // TODO(nick): This should be an error as the const is in the frame which is undesirable. 1091 return nil 1092 } 1093 c, ok := n.rval.Interface().(constant.Value) 1094 if !ok { 1095 // TODO(nick): This should be an error as untyped strings and bools should be constant.Values. 1096 return nil 1097 } 1098 1099 if !representableConst(c, t) { 1100 typ := n.typ.TypeOf() 1101 if isNumber(typ) && isNumber(t) { 1102 // numeric conversion : error msg 1103 // 1104 // integer -> integer : overflows 1105 // integer -> float : overflows (actually not possible) 1106 // float -> integer : truncated 1107 // float -> float : overflows 1108 // 1109 if !isInt(typ) && isInt(t) { 1110 return n.cfgErrorf("%s truncated to %s", c.ExactString(), t.Kind().String()) 1111 } 1112 return n.cfgErrorf("%s overflows %s", c.ExactString(), t.Kind().String()) 1113 } 1114 return n.cfgErrorf("cannot convert %s to %s", c.ExactString(), t.Kind().String()) 1115 } 1116 return nil 1117 } 1118 1119 func (check typecheck) convertConst(v reflect.Value, t reflect.Type) (reflect.Value, error) { 1120 if !v.IsValid() { 1121 // TODO(nick): This should be an error as the const is in the frame which is undesirable. 1122 return v, nil 1123 } 1124 c, ok := v.Interface().(constant.Value) 1125 if !ok { 1126 // TODO(nick): This should be an error as untyped strings and bools should be constant.Values. 1127 return v, nil 1128 } 1129 1130 kind := t.Kind() 1131 switch kind { 1132 case reflect.Bool: 1133 v = reflect.ValueOf(constant.BoolVal(c)) 1134 case reflect.String: 1135 v = reflect.ValueOf(constant.StringVal(c)) 1136 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 1137 i, _ := constant.Int64Val(constant.ToInt(c)) 1138 v = reflect.ValueOf(i).Convert(t) 1139 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 1140 i, _ := constant.Uint64Val(constant.ToInt(c)) 1141 v = reflect.ValueOf(i).Convert(t) 1142 case reflect.Float32: 1143 f, _ := constant.Float32Val(constant.ToFloat(c)) 1144 v = reflect.ValueOf(f) 1145 case reflect.Float64: 1146 f, _ := constant.Float64Val(constant.ToFloat(c)) 1147 v = reflect.ValueOf(f) 1148 case reflect.Complex64: 1149 r, _ := constant.Float32Val(constant.Real(c)) 1150 i, _ := constant.Float32Val(constant.Imag(c)) 1151 v = reflect.ValueOf(complex(r, i)).Convert(t) 1152 case reflect.Complex128: 1153 r, _ := constant.Float64Val(constant.Real(c)) 1154 i, _ := constant.Float64Val(constant.Imag(c)) 1155 v = reflect.ValueOf(complex(r, i)).Convert(t) 1156 default: 1157 return v, errCantConvert 1158 } 1159 return v, nil 1160 } 1161 1162 var bitlen = [...]int{ 1163 reflect.Int: 64, 1164 reflect.Int8: 8, 1165 reflect.Int16: 16, 1166 reflect.Int32: 32, 1167 reflect.Int64: 64, 1168 reflect.Uint: 64, 1169 reflect.Uint8: 8, 1170 reflect.Uint16: 16, 1171 reflect.Uint32: 32, 1172 reflect.Uint64: 64, 1173 reflect.Uintptr: 64, 1174 } 1175 1176 func representableConst(c constant.Value, t reflect.Type) bool { 1177 switch { 1178 case isInt(t): 1179 x := constant.ToInt(c) 1180 if x.Kind() != constant.Int { 1181 return false 1182 } 1183 switch t.Kind() { 1184 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 1185 if _, ok := constant.Int64Val(x); !ok { 1186 return false 1187 } 1188 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 1189 if _, ok := constant.Uint64Val(x); !ok { 1190 return false 1191 } 1192 default: 1193 return false 1194 } 1195 return constant.BitLen(x) <= bitlen[t.Kind()] 1196 case isFloat(t): 1197 x := constant.ToFloat(c) 1198 if x.Kind() != constant.Float { 1199 return false 1200 } 1201 switch t.Kind() { 1202 case reflect.Float32: 1203 f, _ := constant.Float32Val(x) 1204 return !math.IsInf(float64(f), 0) 1205 case reflect.Float64: 1206 f, _ := constant.Float64Val(x) 1207 return !math.IsInf(f, 0) 1208 default: 1209 return false 1210 } 1211 case isComplex(t): 1212 x := constant.ToComplex(c) 1213 if x.Kind() != constant.Complex { 1214 return false 1215 } 1216 switch t.Kind() { 1217 case reflect.Complex64: 1218 r, _ := constant.Float32Val(constant.Real(x)) 1219 i, _ := constant.Float32Val(constant.Imag(x)) 1220 return !math.IsInf(float64(r), 0) && !math.IsInf(float64(i), 0) 1221 case reflect.Complex128: 1222 r, _ := constant.Float64Val(constant.Real(x)) 1223 i, _ := constant.Float64Val(constant.Imag(x)) 1224 return !math.IsInf(r, 0) && !math.IsInf(i, 0) 1225 default: 1226 return false 1227 } 1228 case isString(t): 1229 return c.Kind() == constant.String 1230 case isBoolean(t): 1231 return c.Kind() == constant.Bool 1232 default: 1233 return false 1234 } 1235 } 1236 1237 func isShiftAction(a action) bool { 1238 switch a { 1239 case aShl, aShr, aShlAssign, aShrAssign: 1240 return true 1241 } 1242 return false 1243 } 1244 1245 func isComparisonAction(a action) bool { 1246 switch a { 1247 case aEqual, aNotEqual, aGreater, aGreaterEqual, aLower, aLowerEqual: 1248 return true 1249 } 1250 return false 1251 }