@@ -2795,75 +2795,20 @@ func typecheckcomplit(n *Node) (res *Node) {
2795
2795
yyerror ("invalid composite literal type %v" , t )
2796
2796
n .Type = nil
2797
2797
2798
- case TARRAY , TSLICE :
2799
- // If there are key/value pairs, create a map to keep seen
2800
- // keys so we can check for duplicate indices.
2801
- var indices map [int64 ]bool
2802
- for _ , n1 := range n .List .Slice () {
2803
- if n1 .Op == OKEY {
2804
- indices = make (map [int64 ]bool )
2805
- break
2806
- }
2807
- }
2808
-
2809
- var length , i int64
2810
- checkBounds := t .IsArray () && ! t .IsDDDArray ()
2811
- nl := n .List .Slice ()
2812
- for i2 , l := range nl {
2813
- setlineno (l )
2814
- vp := & nl [i2 ]
2815
- if l .Op == OKEY {
2816
- l .Left = typecheck (l .Left , ctxExpr )
2817
- evconst (l .Left )
2818
- i = indexconst (l .Left )
2819
- if i < 0 {
2820
- if ! l .Left .Diag () {
2821
- if i == - 2 {
2822
- yyerror ("index too large" )
2823
- } else {
2824
- yyerror ("index must be non-negative integer constant" )
2825
- }
2826
- l .Left .SetDiag (true )
2827
- }
2828
- i = - (1 << 30 ) // stay negative for a while
2829
- }
2830
- vp = & l .Right
2831
- }
2832
-
2833
- if i >= 0 && indices != nil {
2834
- if indices [i ] {
2835
- yyerror ("duplicate index in array literal: %d" , i )
2836
- } else {
2837
- indices [i ] = true
2838
- }
2839
- }
2840
-
2841
- r := * vp
2842
- r = pushtype (r , t .Elem ())
2843
- r = typecheck (r , ctxExpr )
2844
- * vp = assignconv (r , t .Elem (), "array or slice literal" )
2845
-
2846
- i ++
2847
- if i > length {
2848
- length = i
2849
- if checkBounds && length > t .NumElem () {
2850
- setlineno (l )
2851
- yyerror ("array index %d out of bounds [0:%d]" , length - 1 , t .NumElem ())
2852
- checkBounds = false
2853
- }
2854
- }
2855
- }
2856
-
2798
+ case TARRAY :
2857
2799
if t .IsDDDArray () {
2800
+ length := typecheckarraylit (t .Elem (), - 1 , n .List .Slice ())
2858
2801
t .SetNumElem (length )
2859
- }
2860
- if t .IsSlice () {
2861
- n .Op = OSLICELIT
2862
- n .Right = nodintconst (length )
2863
2802
} else {
2864
- n .Op = OARRAYLIT
2865
- n .Right = nil
2803
+ typecheckarraylit (t .Elem (), t .NumElem (), n .List .Slice ())
2866
2804
}
2805
+ n .Op = OARRAYLIT
2806
+ n .Right = nil
2807
+
2808
+ case TSLICE :
2809
+ length := typecheckarraylit (t .Elem (), - 1 , n .List .Slice ())
2810
+ n .Op = OSLICELIT
2811
+ n .Right = nodintconst (length )
2867
2812
2868
2813
case TMAP :
2869
2814
var cs constSet
@@ -3017,6 +2962,67 @@ func typecheckcomplit(n *Node) (res *Node) {
3017
2962
return n
3018
2963
}
3019
2964
2965
+ func typecheckarraylit (elemType * types.Type , bound int64 , elts []* Node ) int64 {
2966
+ // If there are key/value pairs, create a map to keep seen
2967
+ // keys so we can check for duplicate indices.
2968
+ var indices map [int64 ]bool
2969
+ for _ , elt := range elts {
2970
+ if elt .Op == OKEY {
2971
+ indices = make (map [int64 ]bool )
2972
+ break
2973
+ }
2974
+ }
2975
+
2976
+ var key , length int64
2977
+ for i , elt := range elts {
2978
+ setlineno (elt )
2979
+ vp := & elts [i ]
2980
+ if elt .Op == OKEY {
2981
+ elt .Left = typecheck (elt .Left , ctxExpr )
2982
+ key = indexconst (elt .Left )
2983
+ if key < 0 {
2984
+ if ! elt .Left .Diag () {
2985
+ if key == - 2 {
2986
+ yyerror ("index too large" )
2987
+ } else {
2988
+ yyerror ("index must be non-negative integer constant" )
2989
+ }
2990
+ elt .Left .SetDiag (true )
2991
+ }
2992
+ key = - (1 << 30 ) // stay negative for a while
2993
+ }
2994
+ vp = & elt .Right
2995
+ }
2996
+
2997
+ r := * vp
2998
+ r = pushtype (r , elemType )
2999
+ r = typecheck (r , ctxExpr )
3000
+ * vp = assignconv (r , elemType , "array or slice literal" )
3001
+
3002
+ if key >= 0 {
3003
+ if indices != nil {
3004
+ if indices [key ] {
3005
+ yyerror ("duplicate index in array literal: %d" , key )
3006
+ } else {
3007
+ indices [key ] = true
3008
+ }
3009
+ }
3010
+
3011
+ if bound >= 0 && key >= bound {
3012
+ yyerror ("array index %d out of bounds [0:%d]" , key , bound )
3013
+ bound = - 1
3014
+ }
3015
+ }
3016
+
3017
+ key ++
3018
+ if key > length {
3019
+ length = key
3020
+ }
3021
+ }
3022
+
3023
+ return length
3024
+ }
3025
+
3020
3026
// visible reports whether sym is exported or locally defined.
3021
3027
func visible (sym * types.Sym ) bool {
3022
3028
return sym != nil && (types .IsExported (sym .Name ) || sym .Pkg == localpkg )
0 commit comments