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