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 "strings"
14 )
15
16
17
18 func (check *Checker) langCompat(lit *syntax.BasicLit) {
19 s := lit.Value
20 if len(s) <= 2 || check.allowVersion(go1_13) {
21 return
22 }
23
24 if strings.Contains(s, "_") {
25 check.versionErrorf(lit, go1_13, "underscore in numeric literal")
26 return
27 }
28 if s[0] != '0' {
29 return
30 }
31 radix := s[1]
32 if radix == 'b' || radix == 'B' {
33 check.versionErrorf(lit, go1_13, "binary literal")
34 return
35 }
36 if radix == 'o' || radix == 'O' {
37 check.versionErrorf(lit, go1_13, "0o/0O-style octal literal")
38 return
39 }
40 if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
41 check.versionErrorf(lit, go1_13, "hexadecimal floating-point literal")
42 }
43 }
44
45 func (check *Checker) basicLit(x *operand, e *syntax.BasicLit) {
46 switch e.Kind {
47 case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
48 check.langCompat(e)
49
50
51
52
53
54
55
56
57
58 const limit = 10000
59 if len(e.Value) > limit {
60 check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
61 x.invalidate()
62 return
63 }
64 }
65 x.setConst(e.Kind, e.Value)
66 if !x.isValid() {
67
68
69
70
71 check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value)
72 x.invalidate()
73 return
74 }
75
76 x.expr = e
77 check.overflow(x, opPos(x.expr))
78 }
79
80 func (check *Checker) funcLit(x *operand, e *syntax.FuncLit) {
81 if sig, ok := check.typ(e.Type).(*Signature); ok {
82
83
84 sig.scope.pos = e.Pos()
85 sig.scope.end = endPos(e)
86 if !check.conf.IgnoreFuncBodies && e.Body != nil {
87
88
89
90 decl := check.decl
91 iota := check.iota
92
93
94
95
96 check.later(func() {
97 check.funcBody(decl, "<function literal>", sig, e.Body, iota)
98 }).describef(e, "func literal")
99 }
100 x.mode_ = value
101 x.typ_ = sig
102 } else {
103 check.errorf(e, InvalidSyntaxTree, "invalid function literal %v", e)
104 x.invalidate()
105 }
106 }
107
108 func (check *Checker) compositeLit(T *target, x *operand, e *syntax.CompositeLit) {
109 var typ, base Type
110 var isElem bool
111
112 switch {
113 case e.Type != nil:
114
115
116
117 if atyp, _ := e.Type.(*syntax.ArrayType); atyp != nil && isdddArray(atyp) {
118
119
120
121 typ = &Array{len: -1, elem: check.varType(atyp.Elem)}
122 } else {
123 typ = check.typ(e.Type)
124 }
125 base = typ
126
127 case T != nil:
128
129 assert(T.typ != nil)
130
131 _ = T.hint || check.verifyVersionf(e, go1_28, "missing type in composite literal")
132 typ = T.typ
133 base = typ
134
135 u, _ := commonUnder(base, nil)
136 if b, ok := deref(u); ok {
137 base = b
138 }
139 isElem = T.hint
140
141 default:
142
143
144 check.error(e, UntypedLit, "missing type in composite literal")
145
146 typ = Typ[Invalid]
147 base = typ
148 }
149
150
151 if !check.isComplete(base) {
152 x.invalidate()
153 return
154 }
155
156 switch u, _ := commonUnder(base, nil); utyp := u.(type) {
157 case *Struct:
158 if len(e.ElemList) == 0 {
159 break
160 }
161
162
163
164 fields := utyp.fields
165 if _, ok := e.ElemList[0].(*syntax.KeyValueExpr); ok {
166
167 visited := make(trie[*Var])
168 for _, e := range e.ElemList {
169 kv, _ := e.(*syntax.KeyValueExpr)
170 if kv == nil {
171 check.error(e, MixedStructLit, "mixture of field:value and value elements in struct literal")
172 continue
173 }
174 key, _ := kv.Key.(*syntax.Name)
175
176
177 if key == nil {
178 check.genericExpr(nil, x, kv.Value)
179 check.errorf(kv, InvalidLitField, "invalid field name %s in struct literal", kv.Key)
180 continue
181 }
182 obj, index, indirect := lookupFieldOrMethod(utyp, false, check.pkg, key.Value, false)
183 if obj == nil {
184 check.genericExpr(nil, x, kv.Value)
185 alt, _, _ := lookupFieldOrMethod(utyp, false, check.pkg, key.Value, true)
186 msg := check.lookupError(base, key.Value, alt, true)
187 check.error(kv.Key, MissingLitField, msg)
188 continue
189 }
190 fld, _ := obj.(*Var)
191 if fld == nil {
192 check.genericExpr(nil, x, kv.Value)
193 check.errorf(kv.Key, MissingLitField, "%s is not a field", kv.Key)
194 continue
195 }
196
197 etyp := fld.typ
198 check.genericExpr(newTarget(etyp, "struct field"), x, kv.Value)
199 if len(index) > 1 && !check.verifyVersionf(kv.Key, go1_27, "use of promoted field %s in struct literal of type %s", fieldPath(utyp, index), base) {
200 continue
201 }
202 if indirect {
203 check.errorf(kv.Key, InvalidLitField, "invalid implicit pointer indirection to reach %s", kv.Key)
204 continue
205 }
206 check.recordUse(key, fld)
207 check.assignment(x, etyp, "struct literal")
208 if alt, n := visited.insert(index, fld); n != 0 {
209 if fld == alt {
210 check.errorf(kv, DuplicateLitField, "duplicate field name %s in struct literal", fld.name)
211 } else if n < len(index) {
212 check.errorf(kv, DuplicateLitField, "cannot specify promoted field %s and enclosing embedded field %s", fld.name, alt.name)
213 } else {
214 check.errorf(kv, DuplicateLitField, "cannot specify embedded field %s and enclosed promoted field %s", fld.name, alt.name)
215 }
216 }
217 }
218 } else {
219
220 for i, e := range e.ElemList {
221 if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
222 check.error(kv, MixedStructLit, "mixture of field:value and value elements in struct literal")
223 continue
224 }
225 if i >= len(fields) {
226 check.genericExpr(nil, x, e)
227 check.errorf(x, InvalidStructLit, "too many values in struct literal of type %s", base)
228 break
229 }
230
231 fld := fields[i]
232 etyp := fld.typ
233 check.genericExpr(newTarget(etyp, "struct field"), x, e)
234 if !fld.Exported() && fld.pkg != check.pkg {
235 check.errorf(x, UnexportedLitField, "implicit assignment to unexported field %s in struct literal of type %s", fld.name, base)
236 continue
237 }
238 check.assignment(x, etyp, "struct literal")
239 }
240 if len(e.ElemList) < len(fields) {
241 var hint string
242 for _, fld := range fields {
243 if !fld.Exported() && fld.pkg != check.pkg {
244 hint = " (type has unexported fields - use key:value pairs)"
245 break
246 }
247 }
248 check.errorf(inNode(e, e.Rbrace), InvalidStructLit, "too few values in struct literal of type %s%s", base, hint)
249
250 }
251 }
252
253 case *Array:
254 n := check.indexedElts(e.ElemList, utyp.elem, utyp.len)
255
256
257
258
259
260
261
262
263 if utyp.len < 0 {
264 utyp.len = n
265
266
267
268
269 if e.Type != nil {
270 check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
271 }
272 }
273
274 case *Slice:
275 check.indexedElts(e.ElemList, utyp.elem, -1)
276
277 case *Map:
278
279
280
281 keyIsInterface := isNonTypeParamInterface(utyp.key)
282 visited := make(map[any][]Type, len(e.ElemList))
283 for _, e := range e.ElemList {
284 kv, _ := e.(*syntax.KeyValueExpr)
285 if kv == nil {
286 check.error(e, MissingLitKey, "missing key in map literal")
287 continue
288 }
289 check.genericExpr(newHint(utyp.key, "map key"), x, kv.Key)
290 check.assignment(x, utyp.key, "map literal")
291 if !x.isValid() {
292 continue
293 }
294 if x.mode() == constant_ {
295 duplicate := false
296 xkey := keyVal(x.val)
297 if keyIsInterface {
298 for _, vtyp := range visited[xkey] {
299 if Identical(vtyp, x.typ()) {
300 duplicate = true
301 break
302 }
303 }
304 visited[xkey] = append(visited[xkey], x.typ())
305 } else {
306 _, duplicate = visited[xkey]
307 visited[xkey] = nil
308 }
309 if duplicate {
310 check.errorf(x, DuplicateLitKey, "duplicate key %s in map literal", x.val)
311 continue
312 }
313 }
314 check.genericExpr(newHint(utyp.elem, "map value"), x, kv.Value)
315 check.assignment(x, utyp.elem, "map literal")
316 }
317
318 default:
319
320
321 for _, e := range e.ElemList {
322 if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
323
324
325
326 e = kv.Value
327 }
328 check.use(e)
329 }
330
331 if isValid(utyp) {
332 var qualifier string
333 if isElem {
334 qualifier = " element"
335 }
336 var cause string
337 if utyp == nil {
338 cause = " (no common underlying type)"
339 }
340 check.errorf(e, InvalidLit, "invalid composite literal%s type %s%s", qualifier, typ, cause)
341 x.invalidate()
342 return
343 }
344 }
345
346 x.mode_ = value
347 x.typ_ = typ
348 }
349
350
351
352
353
354 func (check *Checker) indexedElts(elts []syntax.Expr, typ Type, length int64) int64 {
355 visited := make(map[int64]bool, len(elts))
356 var index, max int64
357 for _, e := range elts {
358
359 validIndex := false
360 eval := e
361 if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
362 if typ, i := check.index(kv.Key, length); isValid(typ) {
363 if i >= 0 {
364 index = i
365 validIndex = true
366 } else {
367 check.errorf(e, InvalidLitIndex, "index %s must be integer constant", kv.Key)
368 }
369 }
370 eval = kv.Value
371 } else if length >= 0 && index >= length {
372 check.errorf(e, OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
373 } else {
374 validIndex = true
375 }
376
377
378 if validIndex {
379 if visited[index] {
380 check.errorf(e, DuplicateLitKey, "duplicate index %d in array or slice literal", index)
381 }
382 visited[index] = true
383 }
384 index++
385 if index > max {
386 max = index
387 }
388
389
390 var x operand
391 check.genericExpr(newHint(typ, "array or slice element"), &x, eval)
392 check.assignment(&x, typ, "array or slice literal")
393 }
394 return max
395 }
396
397
398
399
400
401
402
403
404
405 func keyVal(x constant.Value) any {
406 switch x.Kind() {
407 case constant.Complex:
408 f := constant.ToFloat(x)
409 if f.Kind() != constant.Float {
410 r, _ := constant.Float64Val(constant.Real(x))
411 i, _ := constant.Float64Val(constant.Imag(x))
412 return complex(r, i)
413 }
414 x = f
415 fallthrough
416 case constant.Float:
417 i := constant.ToInt(x)
418 if i.Kind() != constant.Int {
419 v, _ := constant.Float64Val(x)
420 return v
421 }
422 x = i
423 fallthrough
424 case constant.Int:
425 if v, ok := constant.Int64Val(x); ok {
426 return v
427 }
428 if v, ok := constant.Uint64Val(x); ok {
429 return v
430 }
431 case constant.String:
432 return constant.StringVal(x)
433 case constant.Bool:
434 return constant.BoolVal(x)
435 }
436 return x
437 }
438
View as plain text