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