1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements type-checking of identifiers and type expressions.
10 "cmd/compile/internal/syntax"
13 . "internal/types/errors"
17 // ident type-checks identifier e and initializes x with the value or type of e.
18 // If an error occurred, x.mode is set to invalid.
19 // For the meaning of def, see Checker.definedType, below.
20 // If wantType is set, the identifier e is expected to denote a type.
21 func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType bool) {
25 // Note that we cannot use check.lookup here because the returned scope
26 // may be different from obj.Parent(). See also Scope.LookupParent doc.
27 scope, obj := check.scope.LookupParent(e.Value, check.pos)
31 // Blank identifiers are never declared, but the current identifier may
32 // be a placeholder for a receiver type parameter. In this case we can
33 // resolve its type and object from Checker.recvTParamMap.
34 if tpar := check.recvTParamMap[e]; tpar != nil {
38 check.error(e, InvalidBlank, "cannot use _ as value or type")
41 check.errorf(e, UndeclaredName, "undefined: %s", e.Value)
44 case universeAny, universeComparable:
45 if !check.verifyVersionf(e, go1_18, "predeclared %s", e.Value) {
46 return // avoid follow-on errors
49 check.recordUse(e, obj)
51 // Type-check the object.
52 // Only call Checker.objDecl if the object doesn't have a type yet
53 // (in which case we must actually determine it) or the object is a
54 // TypeName and we also want a type (in which case we might detect
55 // a cycle which needs to be reported). Otherwise we can skip the
56 // call and avoid a possible cycle error in favor of the more
57 // informative "not a type/value" error that this function's caller
58 // will issue (see go.dev/issue/25790).
60 if _, gotType := obj.(*TypeName); typ == nil || gotType && wantType {
61 check.objDecl(obj, def)
62 typ = obj.Type() // type must have been assigned by Checker.objDecl
66 // The object may have been dot-imported.
67 // If so, mark the respective package as used.
68 // (This code is only needed for dot-imports. Without them,
69 // we only have to mark variables, see *Var case below).
70 if pkgName := check.dotImportMap[dotImportKey{scope, obj.Name()}]; pkgName != nil {
74 switch obj := obj.(type) {
76 check.errorf(e, InvalidPkgUse, "use of package %s not in selector", obj.name)
84 if obj == universeIota {
85 if check.iota == nil {
86 check.error(e, InvalidIota, "cannot use iota outside constant declaration")
97 if !check.enableAlias && check.isBrokenAlias(obj) {
98 check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", obj.name)
104 // It's ok to mark non-local variables, but ignore variables
105 // from other packages to avoid potential race conditions with
106 // dot-imported variables.
107 if obj.pkg == check.pkg {
110 check.addDeclDep(obj)
117 check.addDeclDep(obj)
134 // typ type-checks the type expression e and returns its type, or Typ[Invalid].
135 // The type must not be an (uninstantiated) generic type.
136 func (check *Checker) typ(e syntax.Expr) Type {
137 return check.definedType(e, nil)
140 // varType type-checks the type expression e and returns its type, or Typ[Invalid].
141 // The type must not be an (uninstantiated) generic type and it must not be a
142 // constraint interface.
143 func (check *Checker) varType(e syntax.Expr) Type {
144 typ := check.definedType(e, nil)
145 check.validVarType(e, typ)
149 // validVarType reports an error if typ is a constraint interface.
150 // The expression e is used for error reporting, if any.
151 func (check *Checker) validVarType(e syntax.Expr, typ Type) {
152 // If we have a type parameter there's nothing to do.
153 if isTypeParam(typ) {
157 // We don't want to call under() or complete interfaces while we are in
158 // the middle of type-checking parameter declarations that might belong
159 // to interface methods. Delay this check to the end of type-checking.
161 if t, _ := under(typ).(*Interface); t != nil {
162 pos := syntax.StartPos(e)
163 tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position?
164 if !tset.IsMethodSet() {
166 check.softErrorf(pos, MisplacedConstraintIface, "cannot use type %s outside a type constraint: interface is (or embeds) comparable", typ)
168 check.softErrorf(pos, MisplacedConstraintIface, "cannot use type %s outside a type constraint: interface contains type constraints", typ)
172 }).describef(e, "check var type %s", typ)
175 // definedType is like typ but also accepts a type name def.
176 // If def != nil, e is the type specification for the type named def, declared
177 // in a type declaration, and def.typ.underlying will be set to the type of e
178 // before any components of e are type-checked.
179 func (check *Checker) definedType(e syntax.Expr, def *TypeName) Type {
180 typ := check.typInternal(e, def)
183 check.errorf(e, WrongTypeArgCount, "cannot use generic type %s without instantiation", typ)
186 check.recordTypeAndValue(e, typexpr, typ, nil)
190 // genericType is like typ but the type must be an (uninstantiated) generic
191 // type. If cause is non-nil and the type expression was a valid type but not
192 // generic, cause will be populated with a message describing the error.
193 func (check *Checker) genericType(e syntax.Expr, cause *string) Type {
194 typ := check.typInternal(e, nil)
196 if isValid(typ) && !isGeneric(typ) {
198 *cause = check.sprintf("%s is not a generic type", typ)
202 // TODO(gri) what is the correct call below?
203 check.recordTypeAndValue(e, typexpr, typ, nil)
207 // goTypeName returns the Go type name for typ and
208 // removes any occurrences of "types2." from that name.
209 func goTypeName(typ Type) string {
210 return strings.ReplaceAll(fmt.Sprintf("%T", typ), "types2.", "")
213 // typInternal drives type checking of types.
214 // Must only be called by definedType or genericType.
215 func (check *Checker) typInternal(e0 syntax.Expr, def *TypeName) (T Type) {
216 if check.conf.Trace {
217 check.trace(e0.Pos(), "-- type %s", e0)
223 // Calling under() here may lead to endless instantiations.
224 // Test case: type T[P any] *T[P]
225 under = safeUnderlying(T)
228 check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T))
230 check.trace(e0.Pos(), "=> %s (under = %s) // %s", T, under, goTypeName(T))
235 switch e := e0.(type) {
236 case *syntax.BadExpr:
237 // ignore - error reported before
241 check.ident(&x, e, def, true)
249 // ignore - error reported before
251 check.errorf(&x, NotAType, "%s used as type", &x)
253 check.errorf(&x, NotAType, "%s is not a type", &x)
256 case *syntax.SelectorExpr:
258 check.selector(&x, e, def, true)
266 // ignore - error reported before
268 check.errorf(&x, NotAType, "%s used as type", &x)
270 check.errorf(&x, NotAType, "%s is not a type", &x)
273 case *syntax.IndexExpr:
274 check.verifyVersionf(e, go1_18, "type instantiation")
275 return check.instantiatedType(e.X, syntax.UnpackListExpr(e.Index), def)
277 case *syntax.ParenExpr:
278 // Generic types must be instantiated before they can be used in any form.
279 // Consequently, generic types cannot be parenthesized.
280 return check.definedType(e.X, def)
282 case *syntax.ArrayType:
286 typ.len = check.arrayLength(e.Len)
289 check.error(e, BadDotDotDotSyntax, "invalid use of [...] array (outside a composite literal)")
292 typ.elem = check.varType(e.Elem)
296 // report error if we encountered [...]
298 case *syntax.SliceType:
301 typ.elem = check.varType(e.Elem)
304 case *syntax.DotsType:
305 // dots are handled explicitly where they are legal
306 // (array composite literals and parameter lists)
307 check.error(e, InvalidDotDotDot, "invalid use of '...'")
310 case *syntax.StructType:
313 check.structType(typ, e)
316 case *syntax.Operation:
317 if e.Op == syntax.Mul && e.Y == nil {
319 typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration
321 typ.base = check.varType(e.X)
322 // If typ.base is invalid, it's unlikely that *base is particularly
323 // useful - even a valid dereferenciation will lead to an invalid
324 // type again, and in some cases we get unexpected follow-on errors
325 // (e.g., go.dev/issue/49005). Return an invalid type instead.
326 if !isValid(typ.base) {
332 check.errorf(e0, NotAType, "%s is not a type", e0)
335 case *syntax.FuncType:
336 typ := new(Signature)
338 check.funcType(typ, nil, nil, e)
341 case *syntax.InterfaceType:
342 typ := check.newInterface()
344 check.interfaceType(typ, e, def)
347 case *syntax.MapType:
351 typ.key = check.varType(e.Key)
352 typ.elem = check.varType(e.Value)
354 // spec: "The comparison operators == and != must be fully defined
355 // for operands of the key type; thus the key type must not be a
356 // function, map, or slice."
358 // Delay this check because it requires fully setup types;
359 // it is safe to continue in any case (was go.dev/issue/6667).
361 if !Comparable(typ.key) {
363 if isTypeParam(typ.key) {
364 why = " (missing comparable constraint)"
366 check.errorf(e.Key, IncomparableMapKey, "invalid map key type %s%s", typ.key, why)
368 }).describef(e.Key, "check map key %s", typ.key)
372 case *syntax.ChanType:
380 case syntax.SendOnly:
382 case syntax.RecvOnly:
385 check.errorf(e, InvalidSyntaxTree, "unknown channel direction %d", e.Dir)
390 typ.elem = check.varType(e.Elem)
394 check.errorf(e0, NotAType, "%s is not a type", e0)
403 func setDefType(def *TypeName, typ Type) {
405 switch t := def.typ.(type) {
407 // t.fromRHS should always be set, either to an invalid type
408 // in the beginning, or to typ in certain cyclic declarations.
409 if t.fromRHS != Typ[Invalid] && t.fromRHS != typ {
410 panic(sprintf(nil, true, "t.fromRHS = %s, typ = %s\n", t.fromRHS, typ))
414 assert(t == Typ[Invalid])
418 panic(fmt.Sprintf("unexpected type %T", t))
423 func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *TypeName) (res Type) {
424 if check.conf.Trace {
425 check.trace(x.Pos(), "-- instantiating type %s with %s", x, xlist)
429 // Don't format the underlying here. It will always be nil.
430 check.trace(x.Pos(), "=> %s", res)
435 gtyp := check.genericType(x, &cause)
437 check.errorf(x, NotAGenericType, invalidOp+"%s%s (%s)", x, xlist, cause)
440 return gtyp // error already reported
443 orig := asNamed(gtyp)
445 panic(fmt.Sprintf("%v: cannot instantiate %v", x.Pos(), gtyp))
448 // evaluate arguments
449 targs := check.typeList(xlist)
451 setDefType(def, Typ[Invalid]) // avoid errors later due to lazy instantiation
455 // create the instance
456 inst := asNamed(check.instance(x.Pos(), orig, targs, nil, check.context()))
457 setDefType(def, inst)
459 // orig.tparams may not be set up, so we need to do expansion later.
461 // This is an instance from the source, not from recursive substitution,
462 // and so it must be resolved during type-checking so that we can report
464 check.recordInstance(x, inst.TypeArgs().list(), inst)
466 if check.validateTArgLen(x.Pos(), inst.TypeParams().Len(), inst.TypeArgs().Len()) {
467 if i, err := check.verify(x.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), check.context()); err != nil {
468 // best position for error reporting
471 pos = syntax.StartPos(xlist[i])
473 check.softErrorf(pos, InvalidTypeArg, "%s", err)
475 check.mono.recordInstance(check.pkg, x.Pos(), inst.TypeParams().list(), inst.TypeArgs().list(), xlist)
479 // TODO(rfindley): remove this call: we don't need to call validType here,
480 // as cycles can only occur for types used inside a Named type declaration,
481 // and so it suffices to call validType from declared types.
482 check.validType(inst)
483 }).describef(x, "resolve instance %s", inst)
488 // arrayLength type-checks the array length expression e
489 // and returns the constant length >= 0, or a value < 0
490 // to indicate an error (and thus an unknown length).
491 func (check *Checker) arrayLength(e syntax.Expr) int64 {
492 // If e is an identifier, the array declaration might be an
493 // attempt at a parameterized type declaration with missing
494 // constraint. Provide an error message that mentions array
496 if name, _ := e.(*syntax.Name); name != nil {
497 obj := check.lookup(name.Value)
499 check.errorf(name, InvalidArrayLen, "undefined array length %s or missing type constraint", name.Value)
502 if _, ok := obj.(*Const); !ok {
503 check.errorf(name, InvalidArrayLen, "invalid array length %s", name.Value)
509 check.expr(nil, &x, e)
510 if x.mode != constant_ {
511 if x.mode != invalid {
512 check.errorf(&x, InvalidArrayLen, "array length %s must be constant", &x)
517 if isUntyped(x.typ) || isInteger(x.typ) {
518 if val := constant.ToInt(x.val); val.Kind() == constant.Int {
519 if representableConst(val, check, Typ[Int], nil) {
520 if n, ok := constant.Int64Val(val); ok && n >= 0 {
528 if isInteger(x.typ) {
529 msg = "invalid array length %s"
531 msg = "array length %s must be integer"
533 check.errorf(&x, InvalidArrayLen, msg, &x)
537 // typeList provides the list of types corresponding to the incoming expression list.
538 // If an error occurred, the result is nil, but all list elements were type-checked.
539 func (check *Checker) typeList(list []syntax.Expr) []Type {
540 res := make([]Type, len(list)) // res != nil even if len(list) == 0
541 for i, x := range list {
542 t := check.varType(x)