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