1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "go/constant"
12 . "internal/types/errors"
13 )
14
15
16
17
18 func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst bool) {
19 check.exprOrType(x, e.X, true)
20
21
22 switch x.mode {
23 case invalid:
24 check.use(e.Index)
25 return false
26
27 case typexpr:
28
29 x.mode = invalid
30
31 x.typ = check.varType(e)
32 if isValid(x.typ) {
33 x.mode = typexpr
34 }
35 return false
36
37 case value:
38 if sig, _ := x.typ.Underlying().(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
39
40 return true
41 }
42 }
43
44
45 check.nonGeneric(nil, x)
46 if x.mode == invalid {
47 return false
48 }
49
50
51 valid := false
52 length := int64(-1)
53 switch typ := x.typ.Underlying().(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, _ := typ.base.Underlying().(*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(nil, &key, index)
96 check.assignment(&key, typ.key, "map index")
97
98 x.mode = mapindex
99 x.typ = typ.elem
100 x.expr = e
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 underIs(x.typ, 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, _ := t.base.Underlying().(*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(nil, &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 check.errorf(e.Pos(), NonSliceableOperand, "cannot index %s", x)
187 check.use(e.Index)
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 *syntax.SliceExpr) {
210 check.expr(nil, x, e.X)
211 if x.mode == invalid {
212 check.use(e.Index[:]...)
213 return
214 }
215
216
217 var ct, cu Type
218 var hasString bool
219 for t, u := range typeset(x.typ) {
220 if u == nil {
221 check.errorf(x, NonSliceableOperand, "cannot slice %s: no specific type in %s", x, x.typ)
222 cu = nil
223 break
224 }
225
226
227 if isString(u) {
228 u = NewSlice(universeByte)
229 hasString = true
230 }
231
232
233 if cu == nil {
234 ct, cu = t, u
235 continue
236 }
237
238
239 if !Identical(cu, u) {
240 check.errorf(x, NonSliceableOperand, "cannot slice %s: %s and %s have different underlying types", x, ct, t)
241 cu = nil
242 break
243 }
244 }
245 if hasString {
246
247
248 cu = Typ[String]
249 if !isTypeParam(x.typ) {
250 cu = x.typ.Underlying()
251 }
252 }
253
254 valid := false
255 length := int64(-1)
256 switch u := cu.(type) {
257 case nil:
258
259 x.mode = invalid
260 return
261
262 case *Basic:
263 if isString(u) {
264 if e.Full {
265 at := e.Index[2]
266 if at == nil {
267 at = e
268 }
269 check.error(at, InvalidSliceExpr, invalidOp+"3-index slice of string")
270 x.mode = invalid
271 return
272 }
273 valid = true
274 if x.mode == constant_ {
275 length = int64(len(constant.StringVal(x.val)))
276 }
277
278
279 if isUntyped(x.typ) {
280 x.typ = Typ[String]
281 }
282 }
283
284 case *Array:
285 valid = true
286 length = u.len
287 if x.mode != variable {
288 check.errorf(x, NonSliceableOperand, "cannot slice unaddressable value %s", x)
289 x.mode = invalid
290 return
291 }
292 x.typ = &Slice{elem: u.elem}
293
294 case *Pointer:
295 if u, _ := u.base.Underlying().(*Array); u != nil {
296 valid = true
297 length = u.len
298 x.typ = &Slice{elem: u.elem}
299 }
300
301 case *Slice:
302 valid = true
303
304 }
305
306 if !valid {
307 check.errorf(x, NonSliceableOperand, "cannot slice %s", x)
308 x.mode = invalid
309 return
310 }
311
312 x.mode = value
313
314
315 if e.Full && (e.Index[1] == nil || e.Index[2] == nil) {
316 check.error(e, InvalidSyntaxTree, "2nd and 3rd index required in 3-index slice")
317 x.mode = invalid
318 return
319 }
320
321
322 var ind [3]int64
323 for i, expr := range e.Index {
324 x := int64(-1)
325 switch {
326 case expr != nil:
327
328
329
330 max := int64(-1)
331 if length >= 0 {
332 max = length + 1
333 }
334 if _, v := check.index(expr, max); v >= 0 {
335 x = v
336 }
337 case i == 0:
338
339 x = 0
340 case length >= 0:
341
342 x = length
343 }
344 ind[i] = x
345 }
346
347
348
349 L:
350 for i, x := range ind[:len(ind)-1] {
351 if x > 0 {
352 for j, y := range ind[i+1:] {
353 if y >= 0 && y < x {
354
355
356
357 check.errorf(e.Index[i+1+j], SwappedSliceIndices, "invalid slice indices: %d < %d", y, x)
358 break L
359 }
360 }
361 }
362 }
363 }
364
365
366
367
368 func (check *Checker) singleIndex(e *syntax.IndexExpr) syntax.Expr {
369 index := e.Index
370 if index == nil {
371 check.errorf(e, InvalidSyntaxTree, "missing index for %s", e.X)
372 return nil
373 }
374 if l, _ := index.(*syntax.ListExpr); l != nil {
375 if n := len(l.ElemList); n <= 1 {
376 check.errorf(e, InvalidSyntaxTree, "invalid use of ListExpr for index expression %v with %d indices", e, n)
377 return nil
378 }
379
380 check.error(l.ElemList[1], InvalidIndex, invalidOp+"more than one index")
381 index = l.ElemList[0]
382 }
383 return index
384 }
385
386
387
388
389
390 func (check *Checker) index(index syntax.Expr, max int64) (typ Type, val int64) {
391 typ = Typ[Invalid]
392 val = -1
393
394 var x operand
395 check.expr(nil, &x, index)
396 if !check.isValidIndex(&x, InvalidIndex, "index", false) {
397 return
398 }
399
400 if x.mode != constant_ {
401 return x.typ, -1
402 }
403
404 if x.val.Kind() == constant.Unknown {
405 return
406 }
407
408 v, ok := constant.Int64Val(x.val)
409 assert(ok)
410 if max >= 0 && v >= max {
411 check.errorf(&x, InvalidIndex, invalidArg+"index %s out of bounds [0:%d]", x.val.String(), max)
412 return
413 }
414
415
416 return x.typ, v
417 }
418
419
420
421
422
423 func (check *Checker) isValidIndex(x *operand, code Code, what string, allowNegative bool) bool {
424 if x.mode == invalid {
425 return false
426 }
427
428
429 check.convertUntyped(x, Typ[Int])
430 if x.mode == invalid {
431 return false
432 }
433
434
435 if !allInteger(x.typ) {
436 check.errorf(x, code, invalidArg+"%s %s must be integer", what, x)
437 return false
438 }
439
440 if x.mode == constant_ {
441
442 if !allowNegative && constant.Sign(x.val) < 0 {
443 check.errorf(x, code, invalidArg+"%s %s must not be negative", what, x)
444 return false
445 }
446
447
448 if !representableConst(x.val, check, Typ[Int], &x.val) {
449 check.errorf(x, code, invalidArg+"%s %s overflows int", what, x)
450 return false
451 }
452 }
453
454 return true
455 }
456
View as plain text