Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(702)

Side by Side Diff: src/pkg/exp/types/expr.go

Issue 6856107: code review 6856107: exp/types: various missing checks for array/slice compo... (Closed)
Patch Set: diff -r 5ff1a3660917 https://code.google.com/p/go Created 11 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/pkg/exp/types/stmt.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // This file implements typechecking of expressions. 5 // This file implements typechecking of expressions.
6 6
7 package types 7 package types
8 8
9 import ( 9 import (
10 "go/ast" 10 "go/ast"
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 // their type after each constant operation. 442 // their type after each constant operation.
443 check.isRepresentable(x, underlying(x.typ).(*Basic)) 443 check.isRepresentable(x, underlying(x.typ).(*Basic))
444 return 444 return
445 } 445 }
446 446
447 x.mode = value 447 x.mode = value
448 // x.typ is unchanged 448 // x.typ is unchanged
449 } 449 }
450 450
451 // index checks an index expression for validity. If length >= 0, it is the uppe r 451 // index checks an index expression for validity. If length >= 0, it is the uppe r
452 // bound for the index. The result is a valid integer constant, or nil. 452 // bound for the index. The result is a valid index >= 0, or a negative value.
453 // 453 //
454 func (check *checker) index(index ast.Expr, length int64, iota int) interface{} { 454 func (check *checker) index(index ast.Expr, length int64, iota int) int64 {
455 var x operand 455 var x operand
456 456
457 check.expr(&x, index, nil, iota) 457 check.expr(&x, index, nil, iota)
458 if !x.isInteger() { 458 if !x.isInteger() {
459 check.errorf(x.pos(), "index %s must be integer", &x) 459 check.errorf(x.pos(), "index %s must be integer", &x)
460 » » return nil 460 » » return -1
461 } 461 }
462 if x.mode != constant { 462 if x.mode != constant {
463 » » return nil // we cannot check more 463 » » return -1 // we cannot check more
464 } 464 }
465 » // x.mode == constant and the index value must be >= 0 465 » // The spec doesn't require int64 indices, but perhaps it should.
466 » if isNegConst(x.val) { 466 » i, ok := x.val.(int64)
467 » if !ok {
468 » » check.errorf(x.pos(), "stupid index %s", &x)
469 » » return -1
470 » }
471 » if i < 0 {
467 check.errorf(x.pos(), "index %s must not be negative", &x) 472 check.errorf(x.pos(), "index %s must not be negative", &x)
468 » » return nil 473 » » return -1
469 } 474 }
470 » // x.val >= 0 475 » if length >= 0 && i >= length {
471 » if length >= 0 && compareConst(x.val, length, token.GEQ) {
472 check.errorf(x.pos(), "index %s is out of bounds (>= %d)", &x, l ength) 476 check.errorf(x.pos(), "index %s is out of bounds (>= %d)", &x, l ength)
473 » » return nil 477 » » return -1
474 } 478 }
475 479
476 » return x.val 480 » return i
481 }
482
483 // indexElts checks the elements (elts) of an array or slice composite literal
484 // against the literals element type (typ), and the element indices against
485 // the literal length if known (length >= 0). It returns the length of the
486 // literal (maximum index value + 1).
487 //
488 func (check *checker) indexedElts(elts []ast.Expr, typ Type, length int64, iota int) int64 {
489 » visited := make(map[int64]bool, len(elts))
490 » var index, max int64
491 » for _, e := range elts {
492 » » // determine and check index
493 » » validIndex := false
494 » » eval := e
495 » » if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
496 » » » if i := check.index(kv.Key, length, iota); i >= 0 {
497 » » » » index = i
498 » » » » validIndex = true
499 » » » }
500 » » » eval = kv.Value
501 » » } else if length >= 0 && index >= length {
502 » » » check.errorf(e.Pos(), "index %d is out of bounds (>= %d) ", index, length)
503 » » } else {
504 » » » validIndex = true
505 » » }
506
507 » » // if we have a valid index, check for duplicate entries
508 » » if validIndex {
509 » » » if visited[index] {
510 » » » » check.errorf(e.Pos(), "duplicate index %d in arr ay or slice literal", index)
511 » » » }
512 » » » visited[index] = true
513 » » }
514 » » index++
515 » » if index > max {
516 » » » max = index
517 » » }
518
519 » » // check element against composite literal element type
520 » » var x operand
521 » » check.expr(&x, eval, typ, iota)
522 » » if !x.isAssignable(typ) {
523 » » » check.errorf(x.pos(), "cannot use %s as %s value in arra y or slice literal", &x, typ)
524 » » }
525 » }
526 » return max
477 } 527 }
478 528
479 func (check *checker) callRecord(x *operand) { 529 func (check *checker) callRecord(x *operand) {
480 if x.mode != invalid { 530 if x.mode != invalid {
481 check.mapf(x.expr, x.typ) 531 check.mapf(x.expr, x.typ)
482 } 532 }
483 } 533 }
484 534
485 // rawExpr typechecks expression e and initializes x with the expression 535 // rawExpr typechecks expression e and initializes x with the expression
486 // value or type. If an error occured, x.mode is set to invalid. 536 // value or type. If an error occured, x.mode is set to invalid.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 case ast.Var: 595 case ast.Var:
546 x.mode = variable 596 x.mode = variable
547 case ast.Fun: 597 case ast.Fun:
548 x.mode = value 598 x.mode = value
549 default: 599 default:
550 unreachable() 600 unreachable()
551 } 601 }
552 x.typ = obj.Type.(Type) 602 x.typ = obj.Type.(Type)
553 603
554 case *ast.Ellipsis: 604 case *ast.Ellipsis:
555 » » unimplemented() 605 » » // ellipses are handled explictly where they are legal
606 » » // (array composite literals and parameter lists)
607 » » check.errorf(e.Pos(), "invalid use of '...'")
608 » » goto Error
556 609
557 case *ast.BasicLit: 610 case *ast.BasicLit:
558 x.setConst(e.Kind, e.Value) 611 x.setConst(e.Kind, e.Value)
559 if x.mode == invalid { 612 if x.mode == invalid {
560 check.invalidAST(e.Pos(), "invalid literal %v", e.Value) 613 check.invalidAST(e.Pos(), "invalid literal %v", e.Value)
561 goto Error 614 goto Error
562 } 615 }
563 616
564 case *ast.FuncLit: 617 case *ast.FuncLit:
565 if typ, ok := check.typ(e.Type, false).(*Signature); ok { 618 if typ, ok := check.typ(e.Type, false).(*Signature); ok {
566 x.mode = value 619 x.mode = value
567 x.typ = typ 620 x.typ = typ
568 check.function(typ, e.Body) 621 check.function(typ, e.Body)
569 } else { 622 } else {
570 check.invalidAST(e.Pos(), "invalid function literal %s", e) 623 check.invalidAST(e.Pos(), "invalid function literal %s", e)
571 goto Error 624 goto Error
572 } 625 }
573 626
574 case *ast.CompositeLit: 627 case *ast.CompositeLit:
575 typ := hint 628 typ := hint
629 openArray := false
576 if e.Type != nil { 630 if e.Type != nil {
577 » » » typ = check.typ(e.Type, false) 631 » » » // [...]T array types may only appear with composite lit erals.
632 » » » // Check for them here so we don't have to handle ... in general.
633 » » » typ = nil
634 » » » if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && at yp.Len != nil {
635 » » » » if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip ! = nil && ellip.Elt == nil {
636 » » » » » // We have an "open" [...]T array type.
637 » » » » » // Create a new ArrayType with unknown l ength (-1)
638 » » » » » // and finish setting it up after analyz ing the literal.
639 » » » » » typ = &Array{Len: -1, Elt: check.typ(aty p.Elt, cycleOk)}
640 » » » » » openArray = true
641 » » » » }
642 » » » }
643 » » » if typ == nil {
644 » » » » typ = check.typ(e.Type, false)
645 » » » }
578 } 646 }
579 if typ == nil { 647 if typ == nil {
580 check.errorf(e.Pos(), "missing type in composite literal ") 648 check.errorf(e.Pos(), "missing type in composite literal ")
581 goto Error 649 goto Error
582 } 650 }
583 651
584 // TODO(gri) try to factor code below better
585
586 switch utyp := underlying(deref(typ)).(type) { 652 switch utyp := underlying(deref(typ)).(type) {
587 case *Struct: 653 case *Struct:
588 if len(e.Elts) == 0 { 654 if len(e.Elts) == 0 {
589 break 655 break
590 } 656 }
591 fields := utyp.Fields 657 fields := utyp.Fields
592 if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok { 658 if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok {
593 // all elements must have keys 659 // all elements must have keys
594 visited := make([]bool, len(fields)) 660 visited := make([]bool, len(fields))
595 for _, e := range e.Elts { 661 for _, e := range e.Elts {
(...skipping 28 matching lines...) Expand all
624 } else { 690 } else {
625 // no element must have a key 691 // no element must have a key
626 for i, e := range e.Elts { 692 for i, e := range e.Elts {
627 if kv, _ := e.(*ast.KeyValueExpr); kv != nil { 693 if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
628 check.errorf(kv.Pos(), "mixture of field:value and value elements in struct literal") 694 check.errorf(kv.Pos(), "mixture of field:value and value elements in struct literal")
629 continue 695 continue
630 } 696 }
631 check.expr(x, e, nil, iota) 697 check.expr(x, e, nil, iota)
632 if i >= len(fields) { 698 if i >= len(fields) {
633 check.errorf(x.pos(), "too many values in struct literal") 699 check.errorf(x.pos(), "too many values in struct literal")
634 » » » » » » goto Error 700 » » » » » » break // cannot continue
635 } 701 }
702 // i < len(fields)
636 etyp := fields[i].Type 703 etyp := fields[i].Type
637 if !x.isAssignable(etyp) { 704 if !x.isAssignable(etyp) {
638 check.errorf(x.pos(), "cannot us e %s as an element of type %s in struct literal", x, etyp) 705 check.errorf(x.pos(), "cannot us e %s as an element of type %s in struct literal", x, etyp)
639 continue 706 continue
640 } 707 }
641 } 708 }
642 if len(e.Elts) < len(fields) { 709 if len(e.Elts) < len(fields) {
643 check.errorf(e.Rbrace, "too few values i n struct literal") 710 check.errorf(e.Rbrace, "too few values i n struct literal")
644 » » » » » goto Error 711 » » » » » // ok to continue
645 } 712 }
646 } 713 }
647 714
648 case *Array: 715 case *Array:
649 » » » var index int64 716 » » » n := check.indexedElts(e.Elts, utyp.Elt, utyp.Len, iota)
650 » » » for _, e := range e.Elts { 717 » » » // if we have an "open" [...]T array, set the length now that we know it
651 » » » » eval := e 718 » » » if openArray {
652 » » » » if kv, _ := e.(*ast.KeyValueExpr); kv != nil { 719 » » » » utyp.Len = n
653 » » » » » check.index(kv.Key, -1, iota)
654 » » » » » eval = kv.Value
655 » » » » }
656 » » » » // TODO(gri) missing index range & duplicate che ck
657 » » » » check.expr(x, eval, utyp.Elt, iota)
658 » » » » if !x.isAssignable(utyp.Elt) {
659 » » » » » check.errorf(x.pos(), "cannot use %s as %s value in array literal", x, utyp.Elt)
660 » » » » }
661 » » » » index++
662 } 720 }
663 721
664 case *Slice: 722 case *Slice:
665 » » » var index int64 723 » » » check.indexedElts(e.Elts, utyp.Elt, -1, iota)
666 » » » for _, e := range e.Elts {
667 » » » » eval := e
668 » » » » if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
669 » » » » » // TODO(gri) check key
670 » » » » » check.index(kv.Key, -1, iota)
671 » » » » » eval = kv.Value
672 » » » » }
673 » » » » // TODO(gri) missing index range & duplicate che ck
674 » » » » check.expr(x, eval, utyp.Elt, iota)
675 » » » » if !x.isAssignable(utyp.Elt) {
676 » » » » » check.errorf(x.pos(), "cannot use %s as %s value in slice literal", x, utyp.Elt)
677 » » » » }
678 » » » » index++
679 » » » }
680 724
681 case *Map: 725 case *Map:
682 visited := make(map[interface{}]bool, len(e.Elts)) 726 visited := make(map[interface{}]bool, len(e.Elts))
683 for _, e := range e.Elts { 727 for _, e := range e.Elts {
684 kv, _ := e.(*ast.KeyValueExpr) 728 kv, _ := e.(*ast.KeyValueExpr)
685 if kv == nil { 729 if kv == nil {
686 check.errorf(e.Pos(), "missing key in ma p literal") 730 check.errorf(e.Pos(), "missing key in ma p literal")
687 continue 731 continue
688 } 732 }
689 check.expr(x, kv.Key, nil, iota) 733 check.expr(x, kv.Key, nil, iota)
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 length := int64(-1) // valid if >= 0 893 length := int64(-1) // valid if >= 0
850 switch typ := underlying(x.typ).(type) { 894 switch typ := underlying(x.typ).(type) {
851 case *Basic: 895 case *Basic:
852 if isString(typ) { 896 if isString(typ) {
853 valid = true 897 valid = true
854 if x.mode == constant { 898 if x.mode == constant {
855 length = int64(len(x.val.(string))) + 1 // +1 for slice 899 length = int64(len(x.val.(string))) + 1 // +1 for slice
856 } 900 }
857 // a sliced string always yields a string value 901 // a sliced string always yields a string value
858 // of the same type as the original string (not 902 // of the same type as the original string (not
859 » » » » // a constant) even if the string and the indexe s 903 » » » » // a constant) even if the string and the indice s
860 // are constant 904 // are constant
861 x.mode = value 905 x.mode = value
862 // x.typ doesn't change 906 // x.typ doesn't change
863 } 907 }
864 908
865 case *Array: 909 case *Array:
866 valid = true 910 valid = true
867 length = typ.Len + 1 // +1 for slice 911 length = typ.Len + 1 // +1 for slice
868 if x.mode != variable { 912 if x.mode != variable {
869 check.invalidOp(x.pos(), "cannot slice %s (value not addressable)", x) 913 check.invalidOp(x.pos(), "cannot slice %s (value not addressable)", x)
870 goto Error 914 goto Error
871 } 915 }
872 x.typ = &Slice{Elt: typ.Elt} 916 x.typ = &Slice{Elt: typ.Elt}
873 917
874 case *Slice: 918 case *Slice:
875 valid = true 919 valid = true
876 x.mode = variable 920 x.mode = variable
877 // x.typ doesn't change 921 // x.typ doesn't change
878 } 922 }
879 923
880 if !valid { 924 if !valid {
881 check.invalidOp(x.pos(), "cannot slice %s", x) 925 check.invalidOp(x.pos(), "cannot slice %s", x)
882 goto Error 926 goto Error
883 } 927 }
884 928
885 » » var lo interface{} = zeroConst 929 » » lo := int64(0)
886 if e.Low != nil { 930 if e.Low != nil {
887 lo = check.index(e.Low, length, iota) 931 lo = check.index(e.Low, length, iota)
888 } 932 }
889 933
890 » » var hi interface{} 934 » » hi := int64(-1)
891 if e.High != nil { 935 if e.High != nil {
892 hi = check.index(e.High, length, iota) 936 hi = check.index(e.High, length, iota)
893 } else if length >= 0 { 937 } else if length >= 0 {
894 hi = length 938 hi = length
895 } 939 }
896 940
897 » » if lo != nil && hi != nil && compareConst(lo, hi, token.GTR) { 941 » » if lo >= 0 && hi >= 0 && lo > hi {
898 » » » check.errorf(e.Low.Pos(), "inverted slice range: %v > %v ", lo, hi) 942 » » » check.errorf(e.Low.Pos(), "inverted slice range: %d > %d ", lo, hi)
899 // ok to continue 943 // ok to continue
900 } 944 }
901 945
902 case *ast.TypeAssertExpr: 946 case *ast.TypeAssertExpr:
903 check.expr(x, e.X, hint, iota) 947 check.expr(x, e.X, hint, iota)
904 if _, ok := underlying(x.typ).(*Interface); !ok { 948 if _, ok := underlying(x.typ).(*Interface); !ok {
905 check.invalidOp(e.X.Pos(), "non-interface type %s in typ e assertion", x.typ) 949 check.invalidOp(e.X.Pos(), "non-interface type %s in typ e assertion", x.typ)
906 // ok to continue 950 // ok to continue
907 } 951 }
908 // TODO(gri) some type asserts are compile-time decidable 952 // TODO(gri) some type asserts are compile-time decidable
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 check.expr(&y, e.Y, hint, iota) 1028 check.expr(&y, e.Y, hint, iota)
985 check.binary(x, &y, e.Op, hint) 1029 check.binary(x, &y, e.Op, hint)
986 1030
987 case *ast.KeyValueExpr: 1031 case *ast.KeyValueExpr:
988 // key:value expressions are handled in composite literals 1032 // key:value expressions are handled in composite literals
989 check.invalidAST(e.Pos(), "no key:value expected") 1033 check.invalidAST(e.Pos(), "no key:value expected")
990 goto Error 1034 goto Error
991 1035
992 case *ast.ArrayType: 1036 case *ast.ArrayType:
993 if e.Len != nil { 1037 if e.Len != nil {
994 » » » var n int64 = -1 1038 » » » check.expr(x, e.Len, nil, iota)
995 » » » if ellip, ok := e.Len.(*ast.Ellipsis); ok { 1039 » » » if x.mode == invalid {
996 » » » » // TODO(gri) need to check somewhere that [...]T types are only used with composite literals 1040 » » » » goto Error
997 » » » » if ellip.Elt != nil { 1041 » » » }
998 » » » » » check.invalidAST(ellip.Pos(), "ellipsis only expected") 1042 » » » if x.mode != constant {
999 » » » » » // ok to continue 1043 » » » » if x.mode != invalid {
1044 » » » » » check.errorf(x.pos(), "array length %s m ust be constant", x)
1000 } 1045 }
1001 » » » } else { 1046 » » » » goto Error
1002 » » » » check.expr(x, e.Len, nil, 0) 1047 » » » }
1003 » » » » if x.mode == invalid { 1048 » » » n, ok := x.val.(int64)
1004 » » » » » goto Error 1049 » » » if !ok || n < 0 {
1005 » » » » } 1050 » » » » check.errorf(x.pos(), "invalid array length %s", x)
1006 » » » » if x.mode == constant { 1051 » » » » goto Error
1007 » » » » » if i, ok := x.val.(int64); ok && i == in t64(int(i)) {
1008 » » » » » » n = i
1009 » » » » » }
1010 » » » » }
1011 » » » » if n < 0 {
1012 » » » » » check.errorf(e.Len.Pos(), "invalid array bound %s", e.Len)
1013 » » » » » // ok to continue
1014 » » » » » n = 0
1015 » » » » }
1016 } 1052 }
1017 x.typ = &Array{Len: n, Elt: check.typ(e.Elt, cycleOk)} 1053 x.typ = &Array{Len: n, Elt: check.typ(e.Elt, cycleOk)}
1018 } else { 1054 } else {
1019 x.typ = &Slice{Elt: check.typ(e.Elt, true)} 1055 x.typ = &Slice{Elt: check.typ(e.Elt, true)}
1020 } 1056 }
1021 x.mode = typexpr 1057 x.mode = typexpr
1022 1058
1023 case *ast.StructType: 1059 case *ast.StructType:
1024 x.mode = typexpr 1060 x.mode = typexpr
1025 x.typ = &Struct{Fields: check.collectFields(e.Fields, cycleOk)} 1061 x.typ = &Struct{Fields: check.collectFields(e.Fields, cycleOk)}
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 // ignore - error reported before 1125 // ignore - error reported before
1090 case novalue: 1126 case novalue:
1091 check.errorf(x.pos(), "%s used as type", &x) 1127 check.errorf(x.pos(), "%s used as type", &x)
1092 case typexpr: 1128 case typexpr:
1093 return x.typ 1129 return x.typ
1094 default: 1130 default:
1095 check.errorf(x.pos(), "%s is not a type", &x) 1131 check.errorf(x.pos(), "%s is not a type", &x)
1096 } 1132 }
1097 return Typ[Invalid] 1133 return Typ[Invalid]
1098 } 1134 }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/exp/types/stmt.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b