arrayLength type-checks the array length expression e and returns the constant length >= 0, or a value < 0 to indicate an error (and thus an unknown length).
(e Expr)
| 508 | // and returns the constant length >= 0, or a value < 0 |
| 509 | // to indicate an error (and thus an unknown length). |
| 510 | func (check *Checker) arrayLength(e Expr) int64 { |
| 511 | // If e is an identifier, the array declaration might be an |
| 512 | // attempt at a parameterized type declaration with missing |
| 513 | // constraint. Provide an error message that mentions array |
| 514 | // length. |
| 515 | if name, _ := e.(*Name); name != nil { |
| 516 | obj := check.lookup(name.Value) |
| 517 | if obj == nil { |
| 518 | check.errorf(name, "undeclared name %s for array length", name.Value) |
| 519 | return -1 |
| 520 | } |
| 521 | if _, ok := obj.(*Const); !ok { |
| 522 | check.errorf(name, "invalid array length %s", name.Value) |
| 523 | return -1 |
| 524 | } |
| 525 | } |
| 526 | |
| 527 | var x operand |
| 528 | check.expr(&x, e) |
| 529 | if x.mode != constant_ { |
| 530 | if x.mode != invalid { |
| 531 | check.errorf(&x, "array length %s must be constant", &x) |
| 532 | } |
| 533 | return -1 |
| 534 | } |
| 535 | |
| 536 | if isUntyped(x.typ) || isInteger(x.typ) { |
| 537 | if val := constant.ToInt(x.val); val.Kind() == constant.Int { |
| 538 | if representableConst(val, check, Typ[Int], nil) { |
| 539 | if n, ok := constant.Int64Val(val); ok && n >= 0 { |
| 540 | return n |
| 541 | } |
| 542 | check.errorf(&x, "invalid array length %s", &x) |
| 543 | return -1 |
| 544 | } |
| 545 | } |
| 546 | } |
| 547 | |
| 548 | check.errorf(&x, "array length %s must be integer", &x) |
| 549 | return -1 |
| 550 | } |
| 551 | |
| 552 | // typeList provides the list of types corresponding to the incoming expression list. |
| 553 | // If an error occurred, the result is nil, but all list elements were type-checked. |
no test coverage detected