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