github.com/gmemcc/yaegi@v0.12.1-0.20221128122509-aa99124c5d16/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 !canIconv(n.typ, 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 aInc: isNumber, 129 aDec: isNumber, 130 aPos: isNumber, 131 aNeg: isNumber, 132 aBitNot: isInt, 133 aNot: canRconvBool, 134 } 135 136 // unaryExpr type checks a unary expression. 137 func (check typecheck) unaryExpr(n *node) error { 138 c0 := n.child[0] 139 if isBlank(c0) { 140 return n.cfgErrorf("cannot use _ as value") 141 } 142 t0 := c0.typ.TypeOf() 143 144 if n.action == aRecv { 145 if !isChan(c0.typ) { 146 return n.cfgErrorf("invalid operation: cannot receive from non-channel %s", c0.typ.id()) 147 } 148 if isSendChan(c0.typ) { 149 return n.cfgErrorf("invalid operation: cannot receive from send-only channel %s", c0.typ.id()) 150 } 151 return nil 152 } 153 154 return check.op(unaryOpPredicates, n.action, n, c0, t0) 155 } 156 157 // shift type checks a shift binary expression. 158 func (check typecheck) shift(n *node) error { 159 c0, c1 := n.child[0], n.child[1] 160 t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf() 161 162 var v0 constant.Value 163 if c0.typ.untyped && c0.rval.IsValid() { 164 v0 = constant.ToInt(c0.rval.Interface().(constant.Value)) 165 c0.rval = reflect.ValueOf(v0) 166 } 167 168 if !(c0.typ.untyped && v0 != nil && v0.Kind() == constant.Int || isInt(t0)) { 169 return n.cfgErrorf("invalid operation: shift of type %v", c0.typ.id()) 170 } 171 172 switch { 173 case c1.typ.untyped: 174 if err := check.convertUntyped(c1, check.scope.getType("uint")); err != nil { 175 return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id()) 176 } 177 case isInt(t1): 178 // nothing to do 179 default: 180 return n.cfgErrorf("invalid operation: shift count type %v, must be integer", c1.typ.id()) 181 } 182 return nil 183 } 184 185 // comparison type checks a comparison binary expression. 186 func (check typecheck) comparison(n *node) error { 187 c0, c1 := n.child[0], n.child[1] 188 189 if !c0.typ.assignableTo(c1.typ) && !c1.typ.assignableTo(c0.typ) && !((isNumber(c0.typ.rtype) || isString(c0.typ.rtype)) && (isNumber(c1.typ.rtype) || isString(c1.typ.rtype))) { 190 return n.cfgErrorf("invalid operation: mismatched types %s and %s", c0.typ.id(), c1.typ.id()) 191 } 192 193 ok := false 194 switch n.action { 195 case aEqual, aNotEqual: 196 ok = c0.typ.comparable() && c1.typ.comparable() || c0.typ.isNil() && c1.typ.hasNil() || c1.typ.isNil() && c0.typ.hasNil() 197 case aLower, aLowerEqual, aGreater, aGreaterEqual: 198 ok = c0.typ.ordered() && c1.typ.ordered() 199 } 200 if !ok { 201 typ := c0.typ 202 if typ.isNil() { 203 typ = c1.typ 204 } 205 if typ.cat != interfaceT && !isNumber(typ.rtype) && !isString(typ.rtype) { 206 return n.cfgErrorf("invalid operation: operator %v not defined on %s", n.action, typ.id()) 207 } 208 } 209 return nil 210 } 211 212 var binaryOpPredicates = opPredicates{ 213 aAdd: func(typ reflect.Type) bool { return isNumber(typ) || isString(typ) }, 214 aSub: isNumber, 215 aMul: isNumber, 216 aQuo: isNumber, 217 aRem: isInt, 218 219 aAnd: isInt, 220 aOr: isInt, 221 aXor: isInt, 222 aAndNot: isInt, 223 224 aLand: isBoolean, 225 aLor: isBoolean, 226 } 227 228 // binaryExpr type checks a binary expression. 229 func (check typecheck) binaryExpr(n *node) error { 230 c0, c1 := n.child[0], n.child[1] 231 232 if isBlank(c0) || isBlank(c1) { 233 return n.cfgErrorf("cannot use _ as value") 234 } 235 236 a := n.action 237 if isAssignAction(a) { 238 a-- 239 } 240 241 if isShiftAction(a) { 242 return check.shift(n) 243 } 244 245 switch n.action { 246 case aAdd: 247 if n.typ == nil { 248 break 249 } 250 case aRem: 251 if zeroConst(c1) { 252 return n.cfgErrorf("invalid operation: division by zero") 253 } 254 case aQuo: 255 if zeroConst(c1) { 256 return n.cfgErrorf("invalid operation: division by zero") 257 } 258 if c0.rval.IsValid() && c1.rval.IsValid() { 259 // Avoid constant conversions below to ensure correct constant integer quotient. 260 return nil 261 } 262 } 263 264 _ = check.convertUntyped(c0, c1.typ) 265 _ = check.convertUntyped(c1, c0.typ) 266 267 if isComparisonAction(a) { 268 return check.comparison(n) 269 } 270 271 return nil 272 } 273 274 func zeroConst(n *node) bool { 275 return n.typ.untyped && constant.Sign(rconvConstNumber(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 for _, c := range n.child { 481 if isBlank(c) { 482 return n.cfgErrorf("cannot use _ as value") 483 } 484 } 485 486 c, child := n.child[0], n.child[1:] 487 488 t := c.typ.TypeOf() 489 var low, high, max *node 490 if len(child) >= 1 { 491 if n.action == aSlice { 492 low = child[0] 493 } else { 494 high = child[0] 495 } 496 } 497 if len(child) >= 2 { 498 if n.action == aSlice { 499 high = child[1] 500 } else { 501 max = child[1] 502 } 503 } 504 if len(child) == 3 && n.action == aSlice { 505 max = child[2] 506 } 507 508 l := -1 509 valid := false 510 switch t.Kind() { 511 case reflect.String: 512 valid = true 513 if c.rval.IsValid() { 514 l = len(vString(c.rval)) 515 } 516 if max != nil { 517 return max.cfgErrorf("invalid operation: 3-index slice of string") 518 } 519 case reflect.Array: 520 valid = true 521 l = t.Len() 522 // TODO(marc): check addressable status of array object (i.e. composite arrays are not). 523 case reflect.Slice: 524 valid = true 525 case reflect.Ptr: 526 if t.Elem().Kind() == reflect.Array { 527 valid = true 528 l = t.Elem().Len() 529 } 530 } 531 if !valid { 532 return c.cfgErrorf("cannot slice type %s", c.typ.id()) 533 } 534 535 var ind [3]int64 536 for i, nod := range []*node{low, high, max} { 537 x := int64(-1) 538 switch { 539 case nod != nil: 540 max := -1 541 if l >= 0 { 542 max = l + 1 543 } 544 if err := check.index(nod, max); err != nil { 545 return err 546 } 547 if nod.rval.IsValid() { 548 x = vInt(nod.rval) 549 } 550 case i == 0: 551 x = 0 552 case l >= 0: 553 x = int64(l) 554 } 555 ind[i] = x 556 } 557 558 for i, x := range ind[:len(ind)-1] { 559 if x <= 0 { 560 continue 561 } 562 for _, y := range ind[i+1:] { 563 if y < 0 || x <= y { 564 continue 565 } 566 return n.cfgErrorf("invalid index values, must be low <= high <= max") 567 } 568 } 569 return nil 570 } 571 572 // typeAssertionExpr type checks a type assert expression. 573 func (check typecheck) typeAssertionExpr(n *node, typ *itype) error { 574 // TODO(nick): This type check is not complete and should be revisited once 575 // https://github.com/golang/go/issues/39717 lands. It is currently impractical to 576 // type check Named types as they cannot be asserted. 577 578 if n.typ.TypeOf().Kind() != reflect.Interface { 579 return n.cfgErrorf("invalid type assertion: non-interface type %s on left", n.typ.id()) 580 } 581 ims := n.typ.methods() 582 if len(ims) == 0 { 583 // Empty interface must be a dynamic check. 584 return nil 585 } 586 587 if isInterface(typ) { 588 // Asserting to an interface is a dynamic check as we must look to the 589 // underlying struct. 590 return nil 591 } 592 593 for name := range ims { 594 im := lookupFieldOrMethod(n.typ, name) 595 tm := lookupFieldOrMethod(typ, name) 596 if im == nil { 597 // This should not be possible. 598 continue 599 } 600 if tm == nil { 601 // Lookup for non-exported methods is impossible 602 // for bin types, ignore them as they can't be used 603 // directly by the interpreted programs. 604 if !token.IsExported(name) && isBin(typ) { 605 continue 606 } 607 return n.cfgErrorf("impossible type assertion: %s does not implement %s (missing %v method)", typ.id(), n.typ.id(), name) 608 } 609 if tm.recv != nil && tm.recv.TypeOf().Kind() == reflect.Ptr && typ.TypeOf().Kind() != reflect.Ptr { 610 return n.cfgErrorf("impossible type assertion: %s does not implement %s as %q method has a pointer receiver", typ.id(), n.typ.id(), name) 611 } 612 613 err := n.cfgErrorf("impossible type assertion: %s does not implement %s", typ.id(), n.typ.id()) 614 if im.numIn() != tm.numIn() || im.numOut() != tm.numOut() { 615 return err 616 } 617 for i := 0; i < im.numIn(); i++ { 618 if !im.in(i).equals(tm.in(i)) { 619 return err 620 } 621 } 622 for i := 0; i < im.numOut(); i++ { 623 if !im.out(i).equals(tm.out(i)) { 624 return err 625 } 626 } 627 } 628 return nil 629 } 630 631 // conversion type checks the conversion of n to typ. 632 func (check typecheck) conversion(n *node, typ *itype) error { 633 var c constant.Value 634 if n.rval.IsValid() { 635 if con, ok := n.rval.Interface().(constant.Value); ok { 636 c = con 637 } 638 } 639 640 var ok bool 641 switch { 642 case c != nil && isConstType(typ): 643 switch t := typ.TypeOf(); { 644 case representableConst(c, t): 645 ok = true 646 case isInt(n.typ.TypeOf()) && isString(t): 647 codepoint := int64(-1) 648 if i, ok := constant.Int64Val(c); ok { 649 codepoint = i 650 } 651 n.rval = reflect.ValueOf(constant.MakeString(string(rune(codepoint)))) 652 ok = true 653 } 654 655 case n.typ.convertibleTo(typ): 656 ok = true 657 } 658 if !ok { 659 return n.cfgErrorf("cannot convert expression of type %s to type %s", n.typ.id(), typ.id()) 660 } 661 if !n.typ.untyped || c == nil { 662 return nil 663 } 664 if isInterface(typ) || !isConstType(typ) { 665 typ = n.typ.defaultType(n.rval, check.scope) 666 } 667 return check.convertUntyped(n, typ) 668 } 669 670 type param struct { 671 nod *node 672 typ *itype 673 } 674 675 func (p param) Type() *itype { 676 if p.typ != nil { 677 return p.typ 678 } 679 return p.nod.typ 680 } 681 682 // unpackParams unpacks child parameters into a slice of param. 683 // If there is only 1 child and it is a callExpr with an n-value return, 684 // the return types are returned, otherwise the original child nodes are 685 // returned with nil typ. 686 func (check typecheck) unpackParams(child []*node) (params []param) { 687 if len(child) == 1 && isCall(child[0]) && child[0].child[0].typ.numOut() > 1 { 688 c0 := child[0] 689 ftyp := child[0].child[0].typ 690 for i := 0; i < ftyp.numOut(); i++ { 691 params = append(params, param{nod: c0, typ: ftyp.out(i)}) 692 } 693 return params 694 } 695 696 for _, c := range child { 697 params = append(params, param{nod: c}) 698 } 699 return params 700 } 701 702 var builtinFuncs = map[string]struct { 703 args int 704 variadic bool 705 }{ 706 bltnAppend: {args: 1, variadic: true}, 707 bltnCap: {args: 1, variadic: false}, 708 bltnClose: {args: 1, variadic: false}, 709 bltnComplex: {args: 2, variadic: false}, 710 bltnImag: {args: 1, variadic: false}, 711 bltnCopy: {args: 2, variadic: false}, 712 bltnDelete: {args: 2, variadic: false}, 713 bltnLen: {args: 1, variadic: false}, 714 bltnMake: {args: 1, variadic: true}, 715 bltnNew: {args: 1, variadic: false}, 716 bltnPanic: {args: 1, variadic: false}, 717 bltnPrint: {args: 0, variadic: true}, 718 bltnPrintln: {args: 0, variadic: true}, 719 bltnReal: {args: 1, variadic: false}, 720 bltnRecover: {args: 0, variadic: false}, 721 } 722 723 func (check typecheck) builtin(name string, n *node, child []*node, ellipsis bool) error { 724 fun := builtinFuncs[name] 725 if ellipsis && name != bltnAppend { 726 return n.cfgErrorf("invalid use of ... with builtin %s", name) 727 } 728 729 var params []param 730 nparams := len(child) 731 switch name { 732 case bltnMake, bltnNew: 733 // Special param handling 734 default: 735 params = check.unpackParams(child) 736 nparams = len(params) 737 } 738 739 if nparams < fun.args { 740 return n.cfgErrorf("not enough arguments in call to %s", name) 741 } else if !fun.variadic && nparams > fun.args { 742 return n.cfgErrorf("too many arguments for %s", name) 743 } 744 745 switch name { 746 case bltnAppend: 747 typ := params[0].Type() 748 t := typ.TypeOf() 749 if t == nil || t.Kind() != reflect.Slice { 750 return params[0].nod.cfgErrorf("first argument to append must be slice; have %s", typ.id()) 751 } 752 753 if nparams == 1 { 754 return nil 755 } 756 // Special case append([]byte, "test"...) is allowed. 757 t1 := params[1].Type() 758 if nparams == 2 && ellipsis && t.Elem().Kind() == reflect.Uint8 && t1.TypeOf().Kind() == reflect.String { 759 if t1.untyped { 760 return check.convertUntyped(params[1].nod, check.scope.getType("string")) 761 } 762 return nil 763 } 764 765 fun := &node{ 766 typ: &itype{ 767 cat: funcT, 768 arg: []*itype{ 769 typ, 770 {cat: variadicT, val: valueTOf(t.Elem())}, 771 }, 772 ret: []*itype{typ}, 773 }, 774 ident: "append", 775 } 776 return check.arguments(n, child, fun, ellipsis) 777 case bltnCap, bltnLen: 778 typ := arrayDeref(params[0].Type()) 779 ok := false 780 switch typ.TypeOf().Kind() { 781 case reflect.Array, reflect.Slice, reflect.Chan, reflect.Interface: 782 ok = true 783 case reflect.String, reflect.Map: 784 ok = name == bltnLen 785 } 786 if !ok { 787 return params[0].nod.cfgErrorf("invalid argument for %s", name) 788 } 789 case bltnClose: 790 p := params[0] 791 typ := p.Type() 792 t := typ.TypeOf() 793 if t.Kind() != reflect.Chan { 794 return p.nod.cfgErrorf("invalid operation: non-chan type %s", p.nod.typ.id()) 795 } 796 if t.ChanDir() == reflect.RecvDir { 797 return p.nod.cfgErrorf("invalid operation: cannot close receive-only channel") 798 } 799 case bltnComplex: 800 var err error 801 p0, p1 := params[0], params[1] 802 typ0, typ1 := p0.Type(), p1.Type() 803 switch { 804 case typ0.untyped && !typ1.untyped: 805 err = check.convertUntyped(p0.nod, typ1) 806 case !typ0.untyped && typ1.untyped: 807 err = check.convertUntyped(p1.nod, typ0) 808 case typ0.untyped && typ1.untyped: 809 fltType := check.scope.getType("float64") 810 err = check.convertUntyped(p0.nod, fltType) 811 if err != nil { 812 break 813 } 814 err = check.convertUntyped(p1.nod, fltType) 815 } 816 if err != nil { 817 return err 818 } 819 820 // check we have the correct types after conversion. 821 typ0, typ1 = p0.Type(), p1.Type() 822 if !typ0.equals(typ1) { 823 return n.cfgErrorf("invalid operation: mismatched types %s and %s", typ0.id(), typ1.id()) 824 } 825 if !isFloat(typ0.TypeOf()) { 826 return n.cfgErrorf("invalid operation: arguments have type %s, expected floating-point", typ0.id()) 827 } 828 case bltnImag, bltnReal: 829 p := params[0] 830 typ := p.Type() 831 if typ.untyped { 832 if err := check.convertUntyped(p.nod, check.scope.getType("complex128")); err != nil { 833 return err 834 } 835 } 836 typ = p.Type() 837 if !isComplex(typ.TypeOf()) { 838 return p.nod.cfgErrorf("invalid argument type %s for %s", typ.id(), name) 839 } 840 case bltnCopy: 841 typ0, typ1 := params[0].Type(), params[1].Type() 842 var t0, t1 reflect.Type 843 if t := typ0.TypeOf(); t.Kind() == reflect.Slice { 844 t0 = t.Elem() 845 } 846 847 switch t := typ1.TypeOf(); t.Kind() { 848 case reflect.String: 849 t1 = reflect.TypeOf(byte(1)) 850 case reflect.Slice: 851 t1 = t.Elem() 852 } 853 854 if t0 == nil || t1 == nil { 855 return n.cfgErrorf("copy expects slice arguments") 856 } 857 if !reflect.DeepEqual(t0, t1) { 858 return n.cfgErrorf("arguments to copy have different element types %s and %s", typ0.id(), typ1.id()) 859 } 860 case bltnDelete: 861 typ := params[0].Type() 862 if typ.TypeOf().Kind() != reflect.Map { 863 return params[0].nod.cfgErrorf("first argument to delete must be map; have %s", typ.id()) 864 } 865 ktyp := params[1].Type() 866 if typ.key != nil && !ktyp.assignableTo(typ.key) { 867 return params[1].nod.cfgErrorf("cannot use %s as type %s in delete", ktyp.id(), typ.key.id()) 868 } 869 case bltnMake: 870 var min int 871 switch child[0].typ.TypeOf().Kind() { 872 case reflect.Slice: 873 min = 2 874 case reflect.Map, reflect.Chan: 875 min = 1 876 default: 877 return child[0].cfgErrorf("cannot make %s; type must be slice, map, or channel", child[0].typ.id()) 878 } 879 if nparams < min { 880 return n.cfgErrorf("not enough arguments in call to make") 881 } else if nparams > min+1 { 882 return n.cfgErrorf("too many arguments for make") 883 } 884 885 var sizes []int 886 for _, c := range child[1:] { 887 if err := check.index(c, -1); err != nil { 888 return err 889 } 890 if c.rval.IsValid() { 891 sizes = append(sizes, int(vInt(c.rval))) 892 } 893 } 894 for len(sizes) == 2 && sizes[0] > sizes[1] { 895 return n.cfgErrorf("len larger than cap in make") 896 } 897 898 case bltnPanic: 899 return check.assignment(params[0].nod, check.scope.getType("interface{}"), "argument to panic") 900 case bltnPrint, bltnPrintln: 901 for _, param := range params { 902 if param.typ != nil { 903 continue 904 } 905 906 if err := check.assignment(param.nod, nil, "argument to "+name); err != nil { 907 return err 908 } 909 } 910 case bltnRecover, bltnNew: 911 // Nothing to do. 912 default: 913 return n.cfgErrorf("unsupported builtin %s", name) 914 } 915 return nil 916 } 917 918 // arrayDeref returns A if typ is *A, otherwise typ. 919 func arrayDeref(typ *itype) *itype { 920 if typ.cat == valueT && typ.TypeOf().Kind() == reflect.Ptr { 921 t := typ.TypeOf() 922 if t.Elem().Kind() == reflect.Array { 923 return valueTOf(t.Elem()) 924 } 925 return typ 926 } 927 928 if typ.cat == ptrT && typ.val.cat == arrayT { 929 return typ.val 930 } 931 return typ 932 } 933 934 // arguments type checks the call expression arguments. 935 func (check typecheck) arguments(n *node, child []*node, fun *node, ellipsis bool) error { 936 params := check.unpackParams(child) 937 l := len(child) 938 if ellipsis { 939 if !fun.typ.isVariadic() { 940 return n.cfgErrorf("invalid use of ..., corresponding parameter is non-variadic") 941 } 942 if len(params) > l { 943 return child[0].cfgErrorf("cannot use ... with %d-valued %s", child[0].child[0].typ.numOut(), child[0].child[0].typ.id()) 944 } 945 } 946 947 var cnt int 948 for i, param := range params { 949 ellip := i == l-1 && ellipsis 950 if err := check.argument(param, fun.typ, cnt, l, ellip); err != nil { 951 return err 952 } 953 cnt++ 954 } 955 956 if fun.typ.isVariadic() { 957 cnt++ 958 } 959 if cnt < fun.typ.numIn() { 960 return n.cfgErrorf("not enough arguments in call to %s", fun.name()) 961 } 962 return nil 963 } 964 965 func (check typecheck) argument(p param, ftyp *itype, i, l int, ellipsis bool) error { 966 atyp := getArg(ftyp, i) 967 if atyp == nil { 968 return p.nod.cfgErrorf("too many arguments") 969 } 970 971 if p.typ == nil && isCall(p.nod) && p.nod.child[0].typ.numOut() != 1 { 972 if l == 1 { 973 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp)) 974 } 975 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), atyp.id()) 976 } 977 978 if ellipsis { 979 if i != ftyp.numIn()-1 { 980 return p.nod.cfgErrorf("can only use ... with matching parameter") 981 } 982 t := p.Type().TypeOf() 983 if t.Kind() != reflect.Slice || !(valueTOf(t.Elem())).assignableTo(atyp) { 984 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.typ.id(), (sliceOf(atyp)).id()) 985 } 986 return nil 987 } 988 989 if p.typ != nil { 990 if !p.typ.assignableTo(atyp) { 991 return p.nod.cfgErrorf("cannot use %s as type %s", p.nod.child[0].typ.id(), getArgsID(ftyp)) 992 } 993 return nil 994 } 995 return check.assignment(p.nod, atyp, "") 996 } 997 998 func getArg(ftyp *itype, i int) *itype { 999 l := ftyp.numIn() 1000 switch { 1001 case ftyp.isVariadic() && i >= l-1: 1002 arg := ftyp.in(l - 1).val 1003 return arg 1004 case i < l: 1005 return ftyp.in(i) 1006 case ftyp.cat == valueT && i < ftyp.rtype.NumIn(): 1007 return valueTOf(ftyp.rtype.In(i)) 1008 default: 1009 return nil 1010 } 1011 } 1012 1013 func getArgsID(ftyp *itype) string { 1014 res := "(" 1015 for i, arg := range ftyp.arg { 1016 if i > 0 { 1017 res += "," 1018 } 1019 res += arg.id() 1020 } 1021 res += ")" 1022 return res 1023 } 1024 1025 var errCantConvert = errors.New("cannot convert") 1026 1027 func (check typecheck) convertUntyped(n *node, typ *itype) error { 1028 if n.typ == nil || !n.typ.untyped || typ == nil { 1029 return nil 1030 } 1031 1032 convErr := n.cfgErrorf("cannot convert %s to %s", n.typ.id(), typ.id()) 1033 1034 ntyp, ttyp := n.typ.TypeOf(), typ.TypeOf() 1035 if typ.untyped { 1036 // Both n and target are untyped. 1037 nkind, tkind := ntyp.Kind(), ttyp.Kind() 1038 if isNumber(ntyp) && isNumber(ttyp) { 1039 if nkind < tkind { 1040 n.typ = typ 1041 } 1042 } else if nkind != tkind { 1043 return convErr 1044 } 1045 return nil 1046 } 1047 1048 var ( 1049 ityp *itype 1050 rtyp reflect.Type 1051 err error 1052 ) 1053 switch { 1054 case typ.isNil() && n.typ.isNil(): 1055 n.typ = typ 1056 return nil 1057 case isNumber(ttyp) || isString(ttyp) || isBoolean(ttyp): 1058 ityp = typ 1059 rtyp = ttyp 1060 case isInterface(typ): 1061 if n.typ.isNil() { 1062 return nil 1063 } 1064 if len(n.typ.methods()) > 0 { // untyped cannot be set to iface 1065 return convErr 1066 } 1067 ityp = n.typ.defaultType(n.rval, check.scope) 1068 rtyp = ntyp 1069 case isArray(typ) || isMap(typ) || isChan(typ) || isFunc(typ) || isPtr(typ): 1070 // TODO(nick): above we are acting on itype, but really it is an rtype check. This is not clear which type 1071 // plain we are in. Fix this later. 1072 if (isArray(typ) || isMap(typ)) && isString(n.typ.rtype) { 1073 return nil 1074 } 1075 if !n.typ.isNil() { 1076 return convErr 1077 } 1078 return nil 1079 default: 1080 return convErr 1081 } 1082 1083 if err := check.representable(n, rtyp); err != nil { 1084 return err 1085 } 1086 n.rval, err = check.convertConst(n.rval, rtyp) 1087 if err != nil { 1088 if errors.Is(err, errCantConvert) { 1089 return convErr 1090 } 1091 return n.cfgErrorf(err.Error()) 1092 } 1093 n.typ = ityp 1094 return nil 1095 } 1096 1097 func (check typecheck) representable(n *node, t reflect.Type) error { 1098 if !n.rval.IsValid() { 1099 // TODO(nick): This should be an error as the const is in the frame which is undesirable. 1100 return nil 1101 } 1102 c, ok := n.rval.Interface().(constant.Value) 1103 if !ok { 1104 // TODO(nick): This should be an error as untyped strings and bools should be constant.Values. 1105 return nil 1106 } 1107 1108 if !representableConst(c, t) { 1109 typ := n.typ.TypeOf() 1110 if isNumber(typ) && isNumber(t) { 1111 // numeric conversion : error msg 1112 // 1113 // integer -> integer : overflows 1114 // integer -> float : overflows (actually not possible) 1115 // float -> integer : truncated 1116 // float -> float : overflows 1117 // 1118 if !isInt(typ) && isInt(t) { 1119 return n.cfgErrorf("%s truncated to %s", c.ExactString(), t.Kind().String()) 1120 } 1121 return n.cfgErrorf("%s overflows %s", c.ExactString(), t.Kind().String()) 1122 } 1123 return n.cfgErrorf("cannot convert %s to %s", c.ExactString(), t.Kind().String()) 1124 } 1125 return nil 1126 } 1127 1128 func (check typecheck) convertConst(v reflect.Value, t reflect.Type) (reflect.Value, error) { 1129 if !v.IsValid() { 1130 // TODO(nick): This should be an error as the const is in the frame which is undesirable. 1131 return v, nil 1132 } 1133 c, ok := v.Interface().(constant.Value) 1134 if !ok { 1135 // TODO(nick): This should be an error as untyped strings and bools should be constant.Values. 1136 return v, nil 1137 } 1138 1139 kind := c.Kind() 1140 switch kind { 1141 case constant.Bool: 1142 v = reflect.ValueOf(constant.BoolVal(c)) 1143 return rconv(v, t) 1144 case constant.String: 1145 v = reflect.ValueOf(constant.StringVal(c)) 1146 return rconv(v, t) 1147 case constant.Int: 1148 val, _ := constant.Int64Val(c) 1149 v = reflect.ValueOf(val) 1150 return rconv(v, t) 1151 case constant.Float: 1152 val, _ := constant.Float64Val(c) 1153 v = reflect.ValueOf(val) 1154 return rconv(v, t) 1155 case constant.Complex: 1156 r, _ := constant.Float32Val(constant.Real(c)) 1157 i, _ := constant.Float32Val(constant.Imag(c)) 1158 return rconv(reflect.ValueOf(complex(r, i)), t) 1159 default: 1160 return v, errCantConvert 1161 } 1162 return v, nil 1163 } 1164 1165 var bitlen = [...]int{ 1166 reflect.Int: 64, 1167 reflect.Int8: 8, 1168 reflect.Int16: 16, 1169 reflect.Int32: 32, 1170 reflect.Int64: 64, 1171 reflect.Uint: 64, 1172 reflect.Uint8: 8, 1173 reflect.Uint16: 16, 1174 reflect.Uint32: 32, 1175 reflect.Uint64: 64, 1176 reflect.Uintptr: 64, 1177 } 1178 1179 func representableConst(c constant.Value, t reflect.Type) bool { 1180 switch { 1181 case isInt(t): 1182 return true 1183 case isFloat(t): 1184 return true 1185 case isComplex(t): 1186 x := constant.ToComplex(c) 1187 if x.Kind() != constant.Complex { 1188 return false 1189 } 1190 switch t.Kind() { 1191 case reflect.Complex64: 1192 r, _ := constant.Float32Val(constant.Real(x)) 1193 i, _ := constant.Float32Val(constant.Imag(x)) 1194 return !math.IsInf(float64(r), 0) && !math.IsInf(float64(i), 0) 1195 case reflect.Complex128: 1196 r, _ := constant.Float64Val(constant.Real(x)) 1197 i, _ := constant.Float64Val(constant.Imag(x)) 1198 return !math.IsInf(r, 0) && !math.IsInf(i, 0) 1199 default: 1200 return false 1201 } 1202 case isString(t): 1203 return true 1204 case isBoolean(t): 1205 return true 1206 default: 1207 return false 1208 } 1209 } 1210 1211 func isShiftAction(a action) bool { 1212 switch a { 1213 case aShl, aShr, aShlAssign, aShrAssign: 1214 return true 1215 } 1216 return false 1217 } 1218 1219 func isComparisonAction(a action) bool { 1220 switch a { 1221 case aEqual, aNotEqual, aGreater, aGreaterEqual, aLower, aLowerEqual: 1222 return true 1223 } 1224 return false 1225 }