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