Source file
src/go/types/typexpr.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "fmt"
11 "go/ast"
12 "go/constant"
13 . "internal/types/errors"
14 "strings"
15 )
16
17
18
19
20 func (check *Checker) ident(x *operand, e *ast.Ident, wantType bool) {
21 x.mode = invalid
22 x.expr = e
23
24 scope, obj := check.lookupScope(e.Name)
25 switch obj {
26 case nil:
27 if e.Name == "_" {
28 check.error(e, InvalidBlank, "cannot use _ as value or type")
29 } else if isValidName(e.Name) {
30 check.errorf(e, UndeclaredName, "undefined: %s", e.Name)
31 }
32 return
33 case universeComparable:
34 if !check.verifyVersionf(e, go1_18, "predeclared %s", e.Name) {
35 return
36 }
37 }
38
39
40 if obj.Name() == "any" && obj.Parent() == Universe {
41 if !check.verifyVersionf(e, go1_18, "predeclared %s", e.Name) {
42 return
43 }
44 }
45 check.recordUse(e, obj)
46
47
48
49
50 _, gotType := obj.(*TypeName)
51 if !gotType && wantType {
52 check.errorf(e, NotAType, "%s (%s) is not a type", obj.Name(), objectKind(obj))
53
54
55
56 if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg {
57 check.usedVars[v] = true
58 }
59 return
60 }
61
62
63
64
65
66
67
68
69
70
71
72
73 typ := obj.Type()
74 if typ == nil || (gotType && wantType && obj.Pkg() == check.pkg) {
75 check.objDecl(obj)
76 typ = obj.Type()
77 }
78 assert(typ != nil)
79
80
81
82
83
84 if pkgName := check.dotImportMap[dotImportKey{scope, obj.Name()}]; pkgName != nil {
85 check.usedPkgNames[pkgName] = true
86 }
87
88 switch obj := obj.(type) {
89 case *PkgName:
90 check.errorf(e, InvalidPkgUse, "use of package %s not in selector", obj.name)
91 return
92
93 case *Const:
94 check.addDeclDep(obj)
95 if !isValid(typ) {
96 return
97 }
98 if obj == universeIota {
99 if check.iota == nil {
100 check.error(e, InvalidIota, "cannot use iota outside constant declaration")
101 return
102 }
103 x.val = check.iota
104 } else {
105 x.val = obj.val
106 }
107 assert(x.val != nil)
108 x.mode = constant_
109
110 case *TypeName:
111 if !check.conf._EnableAlias && check.isBrokenAlias(obj) {
112 check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", obj.name)
113 return
114 }
115 x.mode = typexpr
116
117 case *Var:
118
119
120
121 if obj.pkg == check.pkg {
122 check.usedVars[obj] = true
123 }
124 check.addDeclDep(obj)
125 if !isValid(typ) {
126 return
127 }
128 x.mode = variable
129
130 case *Func:
131 check.addDeclDep(obj)
132 x.mode = value
133
134 case *Builtin:
135 x.id = obj.id
136 x.mode = builtin
137
138 case *Nil:
139 x.mode = value
140
141 default:
142 panic("unreachable")
143 }
144
145 x.typ = typ
146 }
147
148
149
150 func (check *Checker) typ(e ast.Expr) Type {
151 return check.declaredType(e, nil)
152 }
153
154
155
156
157 func (check *Checker) varType(e ast.Expr) Type {
158 typ := check.declaredType(e, nil)
159 check.validVarType(e, typ)
160 return typ
161 }
162
163
164
165 func (check *Checker) validVarType(e ast.Expr, typ Type) {
166
167 if isTypeParam(typ) {
168 return
169 }
170
171
172
173
174 check.later(func() {
175 if t, _ := typ.Underlying().(*Interface); t != nil {
176 tset := computeInterfaceTypeSet(check, e.Pos(), t)
177 if !tset.IsMethodSet() {
178 if tset.comparable {
179 check.softErrorf(e, MisplacedConstraintIface, "cannot use type %s outside a type constraint: interface is (or embeds) comparable", typ)
180 } else {
181 check.softErrorf(e, MisplacedConstraintIface, "cannot use type %s outside a type constraint: interface contains type constraints", typ)
182 }
183 }
184 }
185 }).describef(e, "check var type %s", typ)
186 }
187
188
189
190
191
192 func (check *Checker) declaredType(e ast.Expr, def *TypeName) Type {
193 typ := check.typInternal(e, def)
194 assert(isTyped(typ))
195 if isGeneric(typ) {
196 check.errorf(e, WrongTypeArgCount, "cannot use generic type %s without instantiation", typ)
197 typ = Typ[Invalid]
198 }
199 check.recordTypeAndValue(e, typexpr, typ, nil)
200 return typ
201 }
202
203
204
205
206
207
208
209
210 func (check *Checker) genericType(e ast.Expr, cause *string) Type {
211 typ := check.typInternal(e, nil)
212 assert(isTyped(typ))
213 if isValid(typ) && !isGeneric(typ) {
214 if cause != nil {
215 *cause = check.sprintf("%s is not a generic type", typ)
216 }
217 typ = Typ[Invalid]
218 }
219
220 check.recordTypeAndValue(e, typexpr, typ, nil)
221 return typ
222 }
223
224
225
226 func goTypeName(typ Type) string {
227 return strings.ReplaceAll(fmt.Sprintf("%T", typ), "types.", "")
228 }
229
230
231
232 func (check *Checker) typInternal(e0 ast.Expr, def *TypeName) (T Type) {
233 if check.conf._Trace {
234 check.trace(e0.Pos(), "-- type %s", e0)
235 check.indent++
236 defer func() {
237 check.indent--
238 var under Type
239 if T != nil {
240
241
242 under = safeUnderlying(T)
243 }
244 if T == under {
245 check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T))
246 } else {
247 check.trace(e0.Pos(), "=> %s (under = %s) // %s", T, under, goTypeName(T))
248 }
249 }()
250 }
251
252 switch e := e0.(type) {
253 case *ast.BadExpr:
254
255
256 case *ast.Ident:
257 var x operand
258 check.ident(&x, e, true)
259
260 switch x.mode {
261 case typexpr:
262 return x.typ
263 case invalid:
264
265 case novalue:
266 check.errorf(&x, NotAType, "%s used as type", &x)
267 default:
268 check.errorf(&x, NotAType, "%s is not a type", &x)
269 }
270
271 case *ast.SelectorExpr:
272 var x operand
273 check.selector(&x, e, true)
274
275 switch x.mode {
276 case typexpr:
277 return x.typ
278 case invalid:
279
280 case novalue:
281 check.errorf(&x, NotAType, "%s used as type", &x)
282 default:
283 check.errorf(&x, NotAType, "%s is not a type", &x)
284 }
285
286 case *ast.IndexExpr, *ast.IndexListExpr:
287 ix := unpackIndexedExpr(e)
288 check.verifyVersionf(inNode(e, ix.lbrack), go1_18, "type instantiation")
289 return check.instantiatedType(ix)
290
291 case *ast.ParenExpr:
292
293
294 return check.declaredType(e.X, def)
295
296 case *ast.ArrayType:
297 if e.Len == nil {
298 typ := new(Slice)
299 typ.elem = check.varType(e.Elt)
300 return typ
301 }
302
303 typ := new(Array)
304
305
306 if _, ok := e.Len.(*ast.Ellipsis); ok {
307 check.error(e.Len, BadDotDotDotSyntax, "invalid use of [...] array (outside a composite literal)")
308 typ.len = -1
309 } else {
310 typ.len = check.arrayLength(e.Len)
311 }
312 typ.elem = check.varType(e.Elt)
313 if typ.len >= 0 {
314 return typ
315 }
316
317
318 case *ast.Ellipsis:
319
320 check.error(e, InvalidSyntaxTree, "invalid use of ...")
321
322 case *ast.StructType:
323 typ := new(Struct)
324 check.structType(typ, e)
325 return typ
326
327 case *ast.StarExpr:
328 typ := new(Pointer)
329 typ.base = Typ[Invalid]
330 typ.base = check.varType(e.X)
331
332
333
334
335 if !isValid(typ.base) {
336 return Typ[Invalid]
337 }
338 return typ
339
340 case *ast.FuncType:
341 typ := new(Signature)
342 check.funcType(typ, nil, e)
343 return typ
344
345 case *ast.InterfaceType:
346 typ := check.newInterface()
347 check.interfaceType(typ, e, def)
348 return typ
349
350 case *ast.MapType:
351 typ := new(Map)
352 typ.key = check.varType(e.Key)
353 typ.elem = check.varType(e.Value)
354
355
356
357
358
359
360
361 check.later(func() {
362 if !Comparable(typ.key) {
363 var why string
364 if isTypeParam(typ.key) {
365 why = " (missing comparable constraint)"
366 }
367 check.errorf(e.Key, IncomparableMapKey, "invalid map key type %s%s", typ.key, why)
368 }
369 }).describef(e.Key, "check map key %s", typ.key)
370
371 return typ
372
373 case *ast.ChanType:
374 typ := new(Chan)
375
376 dir := SendRecv
377 switch e.Dir {
378 case ast.SEND | ast.RECV:
379
380 case ast.SEND:
381 dir = SendOnly
382 case ast.RECV:
383 dir = RecvOnly
384 default:
385 check.errorf(e, InvalidSyntaxTree, "unknown channel direction %d", e.Dir)
386
387 }
388
389 typ.dir = dir
390 typ.elem = check.varType(e.Value)
391 return typ
392
393 default:
394 check.errorf(e0, NotAType, "%s is not a type", e0)
395 check.use(e0)
396 }
397
398 typ := Typ[Invalid]
399 return typ
400 }
401
402 func (check *Checker) instantiatedType(ix *indexedExpr) (res Type) {
403 if check.conf._Trace {
404 check.trace(ix.Pos(), "-- instantiating type %s with %s", ix.x, ix.indices)
405 check.indent++
406 defer func() {
407 check.indent--
408
409 check.trace(ix.Pos(), "=> %s", res)
410 }()
411 }
412
413 var cause string
414 typ := check.genericType(ix.x, &cause)
415 if cause != "" {
416 check.errorf(ix.orig, NotAGenericType, invalidOp+"%s (%s)", ix.orig, cause)
417 }
418 if !isValid(typ) {
419 return typ
420 }
421
422 if _, ok := typ.(*Signature); ok {
423 panic("unexpected generic signature")
424 }
425 gtyp := typ.(genericType)
426
427
428 targs := check.typeList(ix.indices)
429 if targs == nil {
430 return Typ[Invalid]
431 }
432
433
434
435
436
437 ityp := check.instance(ix.Pos(), gtyp, targs, nil, check.context())
438 inst, _ := ityp.(genericType)
439 if inst == nil {
440 return Typ[Invalid]
441 }
442
443
444 check.later(func() {
445
446
447
448 check.recordInstance(ix.orig, targs, inst)
449
450 name := inst.(interface{ Obj() *TypeName }).Obj().name
451 tparams := inst.TypeParams().list()
452 if check.validateTArgLen(ix.Pos(), name, len(tparams), len(targs)) {
453
454 if i, err := check.verify(ix.Pos(), inst.TypeParams().list(), targs, check.context()); err != nil {
455
456 pos := ix.Pos()
457 if i < len(ix.indices) {
458 pos = ix.indices[i].Pos()
459 }
460 check.softErrorf(atPos(pos), InvalidTypeArg, "%v", err)
461 } else {
462 check.mono.recordInstance(check.pkg, ix.Pos(), tparams, targs, ix.indices)
463 }
464 }
465 }).describef(ix, "verify instantiation %s", inst)
466
467 return inst
468 }
469
470
471
472
473 func (check *Checker) arrayLength(e ast.Expr) int64 {
474
475
476
477
478 if name, _ := e.(*ast.Ident); name != nil {
479 obj := check.lookup(name.Name)
480 if obj == nil {
481 check.errorf(name, InvalidArrayLen, "undefined array length %s or missing type constraint", name.Name)
482 return -1
483 }
484 if _, ok := obj.(*Const); !ok {
485 check.errorf(name, InvalidArrayLen, "invalid array length %s", name.Name)
486 return -1
487 }
488 }
489
490 var x operand
491 check.expr(nil, &x, e)
492 if x.mode != constant_ {
493 if x.mode != invalid {
494 check.errorf(&x, InvalidArrayLen, "array length %s must be constant", &x)
495 }
496 return -1
497 }
498
499 if isUntyped(x.typ) || isInteger(x.typ) {
500 if val := constant.ToInt(x.val); val.Kind() == constant.Int {
501 if representableConst(val, check, Typ[Int], nil) {
502 if n, ok := constant.Int64Val(val); ok && n >= 0 {
503 return n
504 }
505 }
506 }
507 }
508
509 var msg string
510 if isInteger(x.typ) {
511 msg = "invalid array length %s"
512 } else {
513 msg = "array length %s must be integer"
514 }
515 check.errorf(&x, InvalidArrayLen, msg, &x)
516 return -1
517 }
518
519
520
521 func (check *Checker) typeList(list []ast.Expr) []Type {
522 res := make([]Type, len(list))
523 for i, x := range list {
524 t := check.varType(x)
525 if !isValid(t) {
526 res = nil
527 }
528 if res != nil {
529 res[i] = t
530 }
531 }
532 return res
533 }
534
View as plain text