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/token"
13 . "internal/types/errors"
14 )
15
16
17
18
19 func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) {
20 check.exprOrType(x, e.x, true)
21
22
23 switch x.mode() {
24 case invalid:
25 check.use(e.indices...)
26 return false
27
28 case typexpr:
29
30 x.invalidate()
31
32 x.typ_ = check.varType(e.orig)
33 if isValid(x.typ()) {
34 x.mode_ = typexpr
35 }
36 return false
37
38 case value:
39 if sig, _ := x.typ().Underlying().(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
40
41 return true
42 }
43 }
44
45
46 check.nonGeneric(nil, x)
47 if !x.isValid() {
48 return false
49 }
50
51
52 if !check.isComplete(x.typ()) {
53 x.invalidate()
54 return false
55 }
56 switch typ := x.typ().Underlying().(type) {
57 case *Pointer:
58
59
60 if !check.isComplete(typ.base) {
61 x.invalidate()
62 return false
63 }
64 case *Map:
65
66
67 if !check.isComplete(typ.elem) {
68 x.invalidate()
69 return false
70 }
71 }
72
73
74 valid := false
75 length := int64(-1)
76 switch typ := x.typ().Underlying().(type) {
77 case *Basic:
78 if isString(typ) {
79 valid = true
80 if x.mode() == constant_ {
81 length = constant.StringLen(x.val)
82 }
83
84
85
86 x.mode_ = value
87 x.typ_ = universeByte
88 }
89
90 case *Array:
91 valid = true
92 length = typ.len
93 if x.mode() != variable {
94 x.mode_ = value
95 }
96 x.typ_ = typ.elem
97
98 case *Pointer:
99 if typ, _ := typ.base.Underlying().(*Array); typ != nil {
100 valid = true
101 length = typ.len
102 x.mode_ = variable
103 x.typ_ = typ.elem
104 }
105
106 case *Slice:
107 valid = true
108 x.mode_ = variable
109 x.typ_ = typ.elem
110
111 case *Map:
112 index := check.singleIndex(e)
113 if index == nil {
114 x.invalidate()
115 return false
116 }
117 var key operand
118 check.genericExpr(typ.key, &key, index, nil)
119 check.assignment(&key, typ.key, "map index")
120
121 x.mode_ = mapindex
122 x.typ_ = typ.elem
123 x.expr = e.orig
124 return false
125
126 case *Interface:
127 if !isTypeParam(x.typ()) {
128 break
129 }
130
131 var key, elem Type
132 mode := variable
133
134 if underIs(x.typ(), func(u Type) bool {
135 l := int64(-1)
136 var k, e Type
137 switch t := u.(type) {
138 case *Basic:
139 if isString(t) {
140 e = universeByte
141 mode = value
142 }
143 case *Array:
144 l = t.len
145 e = t.elem
146 if x.mode() != variable {
147 mode = value
148 }
149 case *Pointer:
150 if t, _ := t.base.Underlying().(*Array); t != nil {
151 l = t.len
152 e = t.elem
153 }
154 case *Slice:
155 e = t.elem
156 case *Map:
157 k = t.key
158 e = t.elem
159 }
160 if e == nil {
161 return false
162 }
163 if elem == nil {
164
165 length = l
166 key, elem = k, e
167 return true
168 }
169
170
171 if !Identical(key, k) {
172 return false
173 }
174
175 if !Identical(elem, e) {
176 return false
177 }
178
179 if l >= 0 && l < length {
180 length = l
181 }
182 return true
183 }) {
184
185 if key != nil {
186 index := check.singleIndex(e)
187 if index == nil {
188 x.invalidate()
189 return false
190 }
191 var k operand
192 check.genericExpr(key, &k, index, nil)
193 check.assignment(&k, key, "map index")
194
195 x.mode_ = mapindex
196 x.typ_ = elem
197 x.expr = e.orig
198 return false
199 }
200
201
202 valid = true
203 x.mode_ = mode
204 x.typ_ = elem
205 }
206 }
207
208 if !valid {
209
210 check.errorf(x, NonIndexableOperand, "cannot index %s", x)
211 check.use(e.indices...)
212 x.invalidate()
213 return false
214 }
215
216 index := check.singleIndex(e)
217 if index == nil {
218 x.invalidate()
219 return false
220 }
221
222
223
224
225 if x.typ() == nil {
226 x.typ_ = Typ[Invalid]
227 }
228
229 check.index(index, length)
230 return false
231 }
232
233 func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) {
234 check.expr(nil, nil, x, e.X)
235 if !x.isValid() {
236 check.use(e.Low, e.High, e.Max)
237 return
238 }
239
240
241 var ct, cu Type
242 var hasString bool
243 for t, u := range typeset(x.typ()) {
244 if u == nil {
245 check.errorf(x, NonSliceableOperand, "cannot slice %s: no specific type in %s", x, x.typ())
246 cu = nil
247 break
248 }
249
250
251 if isString(u) {
252 u = NewSlice(universeByte)
253 hasString = true
254 }
255
256
257 if cu == nil {
258 ct, cu = t, u
259 continue
260 }
261
262
263 if !Identical(cu, u) {
264 check.errorf(x, NonSliceableOperand, "cannot slice %s: %s and %s have different underlying types", x, ct, t)
265 cu = nil
266 break
267 }
268 }
269 if hasString {
270
271
272 cu = Typ[String]
273 if !isTypeParam(x.typ()) {
274 cu = x.typ().Underlying()
275 }
276 }
277
278
279
280
281 if p, ok := x.typ().Underlying().(*Pointer); ok && !check.isComplete(p.base) {
282 x.invalidate()
283 return
284 }
285
286 valid := false
287 length := int64(-1)
288 switch u := cu.(type) {
289 case nil:
290
291 x.invalidate()
292 return
293
294 case *Basic:
295 if isString(u) {
296 if e.Slice3 {
297 at := e.Max
298 if at == nil {
299 at = e
300 }
301 check.error(at, InvalidSliceExpr, invalidOp+"3-index slice of string")
302 x.invalidate()
303 return
304 }
305 valid = true
306 if x.mode() == constant_ {
307 length = constant.StringLen(x.val)
308 }
309
310
311 if isUntyped(x.typ()) {
312 x.typ_ = Typ[String]
313 }
314 }
315
316 case *Array:
317 valid = true
318 length = u.len
319 if x.mode() != variable {
320 check.errorf(x, NonSliceableOperand, "cannot slice unaddressable value %s", x)
321 x.invalidate()
322 return
323 }
324 x.typ_ = &Slice{elem: u.elem}
325
326 case *Pointer:
327 if u, _ := u.base.Underlying().(*Array); u != nil {
328 valid = true
329 length = u.len
330 x.typ_ = &Slice{elem: u.elem}
331 }
332
333 case *Slice:
334 valid = true
335
336 }
337
338 if !valid {
339 check.errorf(x, NonSliceableOperand, "cannot slice %s", x)
340 x.invalidate()
341 return
342 }
343
344 x.mode_ = value
345
346
347 if e.Slice3 && (e.High == nil || e.Max == nil) {
348 check.error(inNode(e, e.Rbrack), InvalidSyntaxTree, "2nd and 3rd index required in 3-index slice")
349 x.invalidate()
350 return
351 }
352
353
354 var ind [3]int64
355 for i, expr := range []ast.Expr{e.Low, e.High, e.Max} {
356 x := int64(-1)
357 switch {
358 case expr != nil:
359
360
361
362 max := int64(-1)
363 if length >= 0 {
364 max = length + 1
365 }
366 if _, v := check.index(expr, max); v >= 0 {
367 x = v
368 }
369 case i == 0:
370
371 x = 0
372 case length >= 0:
373
374 x = length
375 }
376 ind[i] = x
377 }
378
379
380
381 L:
382 for i, x := range ind[:len(ind)-1] {
383 if x > 0 {
384 for j, y := range ind[i+1:] {
385 if y >= 0 && y < x {
386
387
388
389 at := []ast.Expr{e.Low, e.High, e.Max}[i+1+j]
390 check.errorf(at, SwappedSliceIndices, "invalid slice indices: %d < %d", y, x)
391 break L
392 }
393 }
394 }
395 }
396 }
397
398
399
400
401 func (check *Checker) singleIndex(expr *indexedExpr) ast.Expr {
402 if len(expr.indices) == 0 {
403 check.errorf(expr.orig, InvalidSyntaxTree, "index expression %v with 0 indices", expr)
404 return nil
405 }
406 if len(expr.indices) > 1 {
407
408 check.error(expr.indices[1], InvalidIndex, invalidOp+"more than one index")
409 }
410 return expr.indices[0]
411 }
412
413
414
415
416
417 func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
418 typ = Typ[Invalid]
419 val = -1
420
421 var x operand
422 check.expr(nil, nil, &x, index)
423 if !check.isValidIndex(&x, InvalidIndex, "index", false) {
424 return
425 }
426
427 if x.mode() != constant_ {
428 return x.typ(), -1
429 }
430
431 if x.val.Kind() == constant.Unknown {
432 return
433 }
434
435 v, ok := constant.Int64Val(x.val)
436 assert(ok)
437 if max >= 0 && v >= max {
438 check.errorf(&x, InvalidIndex, invalidArg+"index %s out of bounds [0:%d]", x.val.String(), max)
439 return
440 }
441
442
443 return x.typ(), v
444 }
445
446 func (check *Checker) isValidIndex(x *operand, code Code, what string, allowNegative bool) bool {
447 if !x.isValid() {
448 return false
449 }
450
451
452 check.convertUntyped(x, Typ[Int])
453 if !x.isValid() {
454 return false
455 }
456
457
458 if !allInteger(x.typ()) {
459 check.errorf(x, code, invalidArg+"%s %s must be integer", what, x)
460 return false
461 }
462
463 if x.mode() == constant_ {
464
465 if !allowNegative && constant.Sign(x.val) < 0 {
466 check.errorf(x, code, invalidArg+"%s %s must not be negative", what, x)
467 return false
468 }
469
470
471 if !representableConst(x.val, check, Typ[Int], &x.val) {
472 check.errorf(x, code, invalidArg+"%s %s overflows int", what, x)
473 return false
474 }
475 }
476
477 return true
478 }
479
480
481
482
483
484
485
486
487
488
489 type indexedExpr struct {
490 orig ast.Expr
491 x ast.Expr
492 lbrack token.Pos
493 indices []ast.Expr
494 rbrack token.Pos
495 }
496
497 func (x *indexedExpr) Pos() token.Pos {
498 return x.orig.Pos()
499 }
500
501 func unpackIndexedExpr(n ast.Node) *indexedExpr {
502 switch e := n.(type) {
503 case *ast.IndexExpr:
504 return &indexedExpr{
505 orig: e,
506 x: e.X,
507 lbrack: e.Lbrack,
508 indices: []ast.Expr{e.Index},
509 rbrack: e.Rbrack,
510 }
511 case *ast.IndexListExpr:
512 return &indexedExpr{
513 orig: e,
514 x: e.X,
515 lbrack: e.Lbrack,
516 indices: e.Indices,
517 rbrack: e.Rbrack,
518 }
519 }
520 return nil
521 }
522
View as plain text