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