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 func (check *Checker) ident(x *operand, e *syntax.Name, wantType bool) {
21 x.mode = invalid
22 x.expr = e
23
24 scope, obj := check.lookupScope(e.Value)
25 switch obj {
26 case nil:
27 if e.Value == "_" {
28 check.error(e, InvalidBlank, "cannot use _ as value or type")
29 } else if isValidName(e.Value) {
30 check.errorf(e, UndeclaredName, "undefined: %s", e.Value)
31 }
32 return
33 case universeComparable:
34 if !check.verifyVersionf(e, go1_18, "predeclared %s", e.Value) {
35 return
36 }
37 }
38
39
40 if obj.Name() == "any" && obj.Parent() == Universe {
41 if !check.verifyVersionf(e, go1_18, "predeclared %s", e.Value) {
42 return
43 }
44 }
45
46 check.recordUse(e, obj)
47
48
49
50
51 _, gotType := obj.(*TypeName)
52 if !gotType && wantType {
53 check.errorf(e, NotAType, "%s is not a type", obj.Name())
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 = nilvalue
140
141 default:
142 panic("unreachable")
143 }
144
145 x.typ = typ
146 }
147
148
149
150 func (check *Checker) typ(e syntax.Expr) Type {
151 return check.declaredType(e, nil)
152 }
153
154
155
156
157 func (check *Checker) varType(e syntax.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 syntax.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 pos := syntax.StartPos(e)
177 tset := computeInterfaceTypeSet(check, pos, t)
178 if !tset.IsMethodSet() {
179 if tset.comparable {
180 check.softErrorf(pos, MisplacedConstraintIface, "cannot use type %s outside a type constraint: interface is (or embeds) comparable", typ)
181 } else {
182 check.softErrorf(pos, MisplacedConstraintIface, "cannot use type %s outside a type constraint: interface contains type constraints", typ)
183 }
184 }
185 }
186 }).describef(e, "check var type %s", typ)
187 }
188
189
190
191
192
193 func (check *Checker) declaredType(e syntax.Expr, def *TypeName) Type {
194 typ := check.typInternal(e, def)
195 assert(isTyped(typ))
196 if isGeneric(typ) {
197 check.errorf(e, WrongTypeArgCount, "cannot use generic type %s without instantiation", typ)
198 typ = Typ[Invalid]
199 }
200 check.recordTypeAndValue(e, typexpr, typ, nil)
201 return typ
202 }
203
204
205
206
207
208
209
210
211 func (check *Checker) genericType(e syntax.Expr, cause *string) Type {
212 typ := check.typInternal(e, nil)
213 assert(isTyped(typ))
214 if isValid(typ) && !isGeneric(typ) {
215 if cause != nil {
216 *cause = check.sprintf("%s is not a generic type", typ)
217 }
218 typ = Typ[Invalid]
219 }
220
221 check.recordTypeAndValue(e, typexpr, typ, nil)
222 return typ
223 }
224
225
226
227 func goTypeName(typ Type) string {
228 return strings.ReplaceAll(fmt.Sprintf("%T", typ), "types2.", "")
229 }
230
231
232
233 func (check *Checker) typInternal(e0 syntax.Expr, def *TypeName) (T Type) {
234 if check.conf.Trace {
235 check.trace(e0.Pos(), "-- type %s", e0)
236 check.indent++
237 defer func() {
238 check.indent--
239 var under Type
240 if T != nil {
241
242
243 under = safeUnderlying(T)
244 }
245 if T == under {
246 check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T))
247 } else {
248 check.trace(e0.Pos(), "=> %s (under = %s) // %s", T, under, goTypeName(T))
249 }
250 }()
251 }
252
253 switch e := e0.(type) {
254 case *syntax.BadExpr:
255
256
257 case *syntax.Name:
258 var x operand
259 check.ident(&x, e, true)
260
261 switch x.mode {
262 case typexpr:
263 return x.typ
264 case invalid:
265
266 case novalue:
267 check.errorf(&x, NotAType, "%s used as type", &x)
268 default:
269 check.errorf(&x, NotAType, "%s is not a type", &x)
270 }
271
272 case *syntax.SelectorExpr:
273 var x operand
274 check.selector(&x, e, true)
275
276 switch x.mode {
277 case typexpr:
278 return x.typ
279 case invalid:
280
281 case novalue:
282 check.errorf(&x, NotAType, "%s used as type", &x)
283 default:
284 check.errorf(&x, NotAType, "%s is not a type", &x)
285 }
286
287 case *syntax.IndexExpr:
288 check.verifyVersionf(e, go1_18, "type instantiation")
289 return check.instantiatedType(e.X, syntax.UnpackListExpr(e.Index))
290
291 case *syntax.ParenExpr:
292
293
294 return check.declaredType(e.X, def)
295
296 case *syntax.ArrayType:
297 typ := new(Array)
298 if e.Len != nil {
299 typ.len = check.arrayLength(e.Len)
300 } else {
301
302 check.error(e, BadDotDotDotSyntax, "invalid use of [...] array (outside a composite literal)")
303 typ.len = -1
304 }
305 typ.elem = check.varType(e.Elem)
306 if typ.len >= 0 {
307 return typ
308 }
309
310
311 case *syntax.SliceType:
312 typ := new(Slice)
313 typ.elem = check.varType(e.Elem)
314 return typ
315
316 case *syntax.DotsType:
317
318 check.error(e, InvalidSyntaxTree, "invalid use of ...")
319
320 case *syntax.StructType:
321 typ := new(Struct)
322 check.structType(typ, e)
323 return typ
324
325 case *syntax.Operation:
326 if e.Op == syntax.Mul && e.Y == nil {
327 typ := new(Pointer)
328 typ.base = Typ[Invalid]
329 typ.base = check.varType(e.X)
330
331
332
333
334 if !isValid(typ.base) {
335 return Typ[Invalid]
336 }
337 return typ
338 }
339
340 check.errorf(e0, NotAType, "%s is not a type", e0)
341 check.use(e0)
342
343 case *syntax.FuncType:
344 typ := new(Signature)
345 check.funcType(typ, nil, nil, e)
346 return typ
347
348 case *syntax.InterfaceType:
349 typ := check.newInterface()
350 check.interfaceType(typ, e, def)
351 return typ
352
353 case *syntax.MapType:
354 typ := new(Map)
355 typ.key = check.varType(e.Key)
356 typ.elem = check.varType(e.Value)
357
358
359
360
361
362
363
364 check.later(func() {
365 if !Comparable(typ.key) {
366 var why string
367 if isTypeParam(typ.key) {
368 why = " (missing comparable constraint)"
369 }
370 check.errorf(e.Key, IncomparableMapKey, "invalid map key type %s%s", typ.key, why)
371 }
372 }).describef(e.Key, "check map key %s", typ.key)
373
374 return typ
375
376 case *syntax.ChanType:
377 typ := new(Chan)
378
379 dir := SendRecv
380 switch e.Dir {
381 case 0:
382
383 case syntax.SendOnly:
384 dir = SendOnly
385 case syntax.RecvOnly:
386 dir = RecvOnly
387 default:
388 check.errorf(e, InvalidSyntaxTree, "unknown channel direction %d", e.Dir)
389
390 }
391
392 typ.dir = dir
393 typ.elem = check.varType(e.Elem)
394 return typ
395
396 default:
397 check.errorf(e0, NotAType, "%s is not a type", e0)
398 check.use(e0)
399 }
400
401 typ := Typ[Invalid]
402 return typ
403 }
404
405 func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr) (res Type) {
406 if check.conf.Trace {
407 check.trace(x.Pos(), "-- instantiating type %s with %s", x, xlist)
408 check.indent++
409 defer func() {
410 check.indent--
411
412 check.trace(x.Pos(), "=> %s", res)
413 }()
414 }
415
416 var cause string
417 typ := check.genericType(x, &cause)
418 if cause != "" {
419 check.errorf(x, NotAGenericType, invalidOp+"%s%s (%s)", x, xlist, cause)
420 }
421 if !isValid(typ) {
422 return typ
423 }
424
425 if _, ok := typ.(*Signature); ok {
426 panic("unexpected generic signature")
427 }
428 gtyp := typ.(genericType)
429
430
431 targs := check.typeList(xlist)
432 if targs == nil {
433 return Typ[Invalid]
434 }
435
436
437
438
439
440 ityp := check.instance(x.Pos(), gtyp, targs, nil, check.context())
441 inst, _ := ityp.(genericType)
442 if inst == nil {
443 return Typ[Invalid]
444 }
445
446
447 check.later(func() {
448
449
450
451 check.recordInstance(x, targs, inst)
452
453 name := inst.(interface{ Obj() *TypeName }).Obj().name
454 tparams := inst.TypeParams().list()
455 if check.validateTArgLen(x.Pos(), name, len(tparams), len(targs)) {
456
457 if i, err := check.verify(x.Pos(), inst.TypeParams().list(), targs, check.context()); err != nil {
458
459 pos := x.Pos()
460 if i < len(xlist) {
461 pos = syntax.StartPos(xlist[i])
462 }
463 check.softErrorf(pos, InvalidTypeArg, "%s", err)
464 } else {
465 check.mono.recordInstance(check.pkg, x.Pos(), tparams, targs, xlist)
466 }
467 }
468 }).describef(x, "verify instantiation %s", inst)
469
470 return inst
471 }
472
473
474
475
476 func (check *Checker) arrayLength(e syntax.Expr) int64 {
477
478
479
480
481 if name, _ := e.(*syntax.Name); name != nil {
482 obj := check.lookup(name.Value)
483 if obj == nil {
484 check.errorf(name, InvalidArrayLen, "undefined array length %s or missing type constraint", name.Value)
485 return -1
486 }
487 if _, ok := obj.(*Const); !ok {
488 check.errorf(name, InvalidArrayLen, "invalid array length %s", name.Value)
489 return -1
490 }
491 }
492
493 var x operand
494 check.expr(nil, &x, e)
495 if x.mode != constant_ {
496 if x.mode != invalid {
497 check.errorf(&x, InvalidArrayLen, "array length %s must be constant", &x)
498 }
499 return -1
500 }
501
502 if isUntyped(x.typ) || isInteger(x.typ) {
503 if val := constant.ToInt(x.val); val.Kind() == constant.Int {
504 if representableConst(val, check, Typ[Int], nil) {
505 if n, ok := constant.Int64Val(val); ok && n >= 0 {
506 return n
507 }
508 }
509 }
510 }
511
512 var msg string
513 if isInteger(x.typ) {
514 msg = "invalid array length %s"
515 } else {
516 msg = "array length %s must be integer"
517 }
518 check.errorf(&x, InvalidArrayLen, msg, &x)
519 return -1
520 }
521
522
523
524 func (check *Checker) typeList(list []syntax.Expr) []Type {
525 res := make([]Type, len(list))
526 for i, x := range list {
527 t := check.varType(x)
528 if !isValid(t) {
529 res = nil
530 }
531 if res != nil {
532 res[i] = t
533 }
534 }
535 return res
536 }
537
View as plain text