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