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