Source file
src/go/types/index.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "go/ast"
11 "go/constant"
12 "go/internal/typeparams"
13 )
14
15
16
17
18 func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) {
19 check.exprOrType(x, e.X)
20
21 switch x.mode {
22 case invalid:
23 check.use(typeparams.UnpackExpr(e.Index)...)
24 return false
25
26 case typexpr:
27
28 x.mode = invalid
29 x.typ = check.varType(e)
30 if x.typ != Typ[Invalid] {
31 x.mode = typexpr
32 }
33 return false
34
35 case value:
36 if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 {
37
38 return true
39 }
40 }
41
42 valid := false
43 length := int64(-1)
44 switch typ := optype(x.typ).(type) {
45 case *Basic:
46 if isString(typ) {
47 valid = true
48 if x.mode == constant_ {
49 length = int64(len(constant.StringVal(x.val)))
50 }
51
52
53
54 x.mode = value
55 x.typ = universeByte
56 }
57
58 case *Array:
59 valid = true
60 length = typ.len
61 if x.mode != variable {
62 x.mode = value
63 }
64 x.typ = typ.elem
65
66 case *Pointer:
67 if typ := asArray(typ.base); typ != nil {
68 valid = true
69 length = typ.len
70 x.mode = variable
71 x.typ = typ.elem
72 }
73
74 case *Slice:
75 valid = true
76 x.mode = variable
77 x.typ = typ.elem
78
79 case *Map:
80 index := check.singleIndex(e)
81 if index == nil {
82 x.mode = invalid
83 return
84 }
85 var key operand
86 check.expr(&key, index)
87 check.assignment(&key, typ.key, "map index")
88
89 x.mode = mapindex
90 x.typ = typ.elem
91 x.expr = e
92 return
93
94 case *_Sum:
95
96
97
98 var tkey, telem Type
99 nmaps := 0
100 if typ.is(func(t Type) bool {
101 var e Type
102 switch t := under(t).(type) {
103 case *Basic:
104 if isString(t) {
105 e = universeByte
106 }
107 case *Array:
108 e = t.elem
109 case *Pointer:
110 if t := asArray(t.base); t != nil {
111 e = t.elem
112 }
113 case *Slice:
114 e = t.elem
115 case *Map:
116
117
118
119
120 if tkey != nil && !Identical(t.key, tkey) {
121 return false
122 }
123 tkey = t.key
124 e = t.elem
125 nmaps++
126 case *_TypeParam:
127 check.errorf(x, 0, "type of %s contains a type parameter - cannot index (implementation restriction)", x)
128 case *instance:
129 panic("unimplemented")
130 }
131 if e == nil || telem != nil && !Identical(e, telem) {
132 return false
133 }
134 telem = e
135 return true
136 }) {
137
138
139 if nmaps > 0 {
140 index := check.singleIndex(e)
141 if index == nil {
142 x.mode = invalid
143 return
144 }
145 var key operand
146 check.expr(&key, index)
147 check.assignment(&key, tkey, "map index")
148
149
150
151 if nmaps == len(typ.types) {
152 x.mode = mapindex
153 x.typ = telem
154 x.expr = e
155 return
156 }
157
158
159
160
161 valid = isInteger(tkey)
162
163 if !valid && key.mode == invalid {
164 x.mode = invalid
165 return
166 }
167 x.mode = value
168 } else {
169
170 valid = true
171 x.mode = variable
172 }
173 x.typ = telem
174 }
175 }
176
177 if !valid {
178 check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
179 x.mode = invalid
180 return
181 }
182
183 index := check.singleIndex(e)
184 if index == nil {
185 x.mode = invalid
186 return
187 }
188
189
190
191
192 if x.typ == nil {
193 x.typ = Typ[Invalid]
194 }
195
196 check.index(index, length)
197 return false
198 }
199
200 func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) {
201 check.expr(x, e.X)
202 if x.mode == invalid {
203 check.use(e.Low, e.High, e.Max)
204 return
205 }
206
207 valid := false
208 length := int64(-1)
209 switch typ := optype(x.typ).(type) {
210 case *Basic:
211 if isString(typ) {
212 if e.Slice3 {
213 check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string")
214 x.mode = invalid
215 return
216 }
217 valid = true
218 if x.mode == constant_ {
219 length = int64(len(constant.StringVal(x.val)))
220 }
221
222
223 if typ.kind == UntypedString {
224 x.typ = Typ[String]
225 }
226 }
227
228 case *Array:
229 valid = true
230 length = typ.len
231 if x.mode != variable {
232 check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x)
233 x.mode = invalid
234 return
235 }
236 x.typ = &Slice{elem: typ.elem}
237
238 case *Pointer:
239 if typ := asArray(typ.base); typ != nil {
240 valid = true
241 length = typ.len
242 x.typ = &Slice{elem: typ.elem}
243 }
244
245 case *Slice:
246 valid = true
247
248
249 case *_Sum, *_TypeParam:
250 check.errorf(x, 0, "generic slice expressions not yet implemented")
251 x.mode = invalid
252 return
253 }
254
255 if !valid {
256 check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x)
257 x.mode = invalid
258 return
259 }
260
261 x.mode = value
262
263
264 if e.Slice3 && (e.High == nil || e.Max == nil) {
265 check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice")
266 x.mode = invalid
267 return
268 }
269
270
271 var ind [3]int64
272 for i, expr := range []ast.Expr{e.Low, e.High, e.Max} {
273 x := int64(-1)
274 switch {
275 case expr != nil:
276
277
278
279 max := int64(-1)
280 if length >= 0 {
281 max = length + 1
282 }
283 if _, v := check.index(expr, max); v >= 0 {
284 x = v
285 }
286 case i == 0:
287
288 x = 0
289 case length >= 0:
290
291 x = length
292 }
293 ind[i] = x
294 }
295
296
297
298 L:
299 for i, x := range ind[:len(ind)-1] {
300 if x > 0 {
301 for _, y := range ind[i+1:] {
302 if y >= 0 && x > y {
303 check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y)
304 break L
305 }
306 }
307 }
308 }
309 }
310
311
312
313
314 func (check *Checker) singleIndex(e *ast.IndexExpr) ast.Expr {
315 index := e.Index
316 if index == nil {
317 check.invalidAST(e, "missing index for %s", e)
318 return nil
319 }
320
321 indexes := typeparams.UnpackExpr(index)
322 if len(indexes) == 0 {
323 check.invalidAST(index, "index expression %v with 0 indices", index)
324 return nil
325 }
326 if len(indexes) > 1 {
327
328 check.invalidOp(indexes[1], _InvalidIndex, "more than one index")
329 }
330 return indexes[0]
331 }
332
333
334
335
336
337 func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
338 typ = Typ[Invalid]
339 val = -1
340
341 var x operand
342 check.expr(&x, index)
343 if !check.isValidIndex(&x, _InvalidIndex, "index", false) {
344 return
345 }
346
347 if x.mode != constant_ {
348 return x.typ, -1
349 }
350
351 if x.val.Kind() == constant.Unknown {
352 return
353 }
354
355 v, ok := constant.Int64Val(x.val)
356 assert(ok)
357 if max >= 0 && v >= max {
358 check.invalidArg(&x, _InvalidIndex, "index %s is out of bounds", &x)
359 return
360 }
361
362
363 return x.typ, v
364 }
365
366 func (check *Checker) isValidIndex(x *operand, code errorCode, what string, allowNegative bool) bool {
367 if x.mode == invalid {
368 return false
369 }
370
371
372 check.convertUntyped(x, Typ[Int])
373 if x.mode == invalid {
374 return false
375 }
376
377
378 if !isInteger(x.typ) {
379 check.invalidArg(x, code, "%s %s must be integer", what, x)
380 return false
381 }
382
383 if x.mode == constant_ {
384
385 if !allowNegative && constant.Sign(x.val) < 0 {
386 check.invalidArg(x, code, "%s %s must not be negative", what, x)
387 return false
388 }
389
390
391 if !representableConst(x.val, check, Typ[Int], &x.val) {
392 check.invalidArg(x, code, "%s %s overflows int", what, x)
393 return false
394 }
395 }
396
397 return true
398 }
399
400
401
402
403
404
405 func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 {
406 visited := make(map[int64]bool, len(elts))
407 var index, max int64
408 for _, e := range elts {
409
410 validIndex := false
411 eval := e
412 if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
413 if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] {
414 if i >= 0 {
415 index = i
416 validIndex = true
417 } else {
418 check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key)
419 }
420 }
421 eval = kv.Value
422 } else if length >= 0 && index >= length {
423 check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
424 } else {
425 validIndex = true
426 }
427
428
429 if validIndex {
430 if visited[index] {
431 check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index)
432 }
433 visited[index] = true
434 }
435 index++
436 if index > max {
437 max = index
438 }
439
440
441 var x operand
442 check.exprWithHint(&x, eval, typ)
443 check.assignment(&x, typ, "array or slice literal")
444 }
445 return max
446 }
447
View as plain text