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.
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 and path, see check.typ, below.
21 func (check
*Checker
) ident(x
*operand
, e
*ast
.Ident
, def
*Named
, path
[]*TypeName
) {
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
.Name
, check
.pos
)
30 check
.errorf(e
.Pos(), "cannot use _ as value or type")
32 check
.errorf(e
.Pos(), "undeclared name: %s", e
.Name
)
36 check
.recordUse(e
, obj
)
38 check
.objDecl(obj
, def
, path
)
42 // The object may be dot-imported: If so, remove its package from
43 // the map of unused dot imports for the respective file scope.
44 // (This code is only needed for dot-imports. Without them,
45 // we only have to mark variables, see *Var case below).
46 if pkg
:= obj
.Pkg(); pkg
!= check
.pkg
&& pkg
!= nil {
47 delete(check
.unusedDotImports
[scope
], pkg
)
50 switch obj
:= obj
.(type) {
52 check
.errorf(e
.Pos(), "use of package %s not in selector", obj
.name
)
57 if typ
== Typ
[Invalid
] {
60 if obj
== universeIota
{
61 if check
.iota == nil {
62 check
.errorf(e
.Pos(), "cannot use iota outside constant declaration")
74 // package-level alias cycles are now checked by Checker.objDecl
76 if check
.objMap
[obj
] != nil {
80 if check
.cycle(obj
, path
, true) {
81 // maintain x.mode == typexpr despite error
87 // It's ok to mark non-local variables, but ignore variables
88 // from other packages to avoid potential race conditions with
89 // dot-imported variables.
90 if obj
.pkg
== check
.pkg
{
94 if typ
== Typ
[Invalid
] {
100 check
.addDeclDep(obj
)
117 // cycle reports whether obj appears in path or not.
118 // If it does, and report is set, it also reports a cycle error.
119 func (check
*Checker
) cycle(obj
*TypeName
, path
[]*TypeName
, report
bool) bool {
120 // (it's ok to iterate forward because each named type appears at most once in path)
121 for i
, prev
:= range path
{
124 check
.errorf(obj
.pos
, "illegal cycle in declaration of %s", obj
.name
)
126 for _
, obj
:= range path
[i
:] {
127 check
.errorf(obj
.Pos(), "\t%s refers to", obj
.Name()) // secondary error, \t indented
129 check
.errorf(obj
.Pos(), "\t%s", obj
.Name())
137 // typExpr type-checks the type expression e and returns its type, or Typ[Invalid].
138 // If def != nil, e is the type specification for the named type def, declared
139 // in a type declaration, and def.underlying will be set to the type of e before
140 // any components of e are type-checked. Path contains the path of named types
141 // referring to this type; i.e. it is the path of named types directly containing
142 // each other and leading to the current type e. Indirect containment (e.g. via
143 // pointer indirection, function parameter, etc.) breaks the path (leads to a new
144 // path, and usually via calling Checker.typ below) and those types are not found
147 func (check
*Checker
) typExpr(e ast
.Expr
, def
*Named
, path
[]*TypeName
) (T Type
) {
149 check
.trace(e
.Pos(), "%s", e
)
153 check
.trace(e
.Pos(), "=> %s", T
)
157 T
= check
.typExprInternal(e
, def
, path
)
159 check
.recordTypeAndValue(e
, typexpr
, T
, nil)
164 // typ is like typExpr (with a nil argument for the def parameter),
165 // but typ breaks type cycles. It should be called for components of
166 // types that break cycles, such as pointer base types, slice or map
167 // element types, etc. See the comment in typExpr for details.
169 func (check
*Checker
) typ(e ast
.Expr
) Type
{
170 // typExpr is called with a nil path indicating an indirection:
171 // push indir sentinel on object path
176 return check
.typExpr(e
, nil, nil)
179 // funcType type-checks a function or method type.
180 func (check
*Checker
) funcType(sig
*Signature
, recvPar
*ast
.FieldList
, ftyp
*ast
.FuncType
) {
181 scope
:= NewScope(check
.scope
, token
.NoPos
, token
.NoPos
, "function")
183 check
.recordScope(ftyp
, scope
)
185 recvList
, _
:= check
.collectParams(scope
, recvPar
, false)
186 params
, variadic
:= check
.collectParams(scope
, ftyp
.Params
, true)
187 results
, _
:= check
.collectParams(scope
, ftyp
.Results
, false)
190 // recv parameter list present (may be empty)
191 // spec: "The receiver is specified via an extra parameter section preceding the
192 // method name. That parameter section must declare a single parameter, the receiver."
194 switch len(recvList
) {
196 check
.error(recvPar
.Pos(), "method is missing receiver")
197 recv
= NewParam(0, nil, "", Typ
[Invalid
]) // ignore recv below
199 // more than one receiver
200 check
.error(recvList
[len(recvList
)-1].Pos(), "method must have exactly one receiver")
201 fallthrough // continue with first receiver
205 // spec: "The receiver type must be of the form T or *T where T is a type name."
206 // (ignore invalid types - error was reported before)
207 if t
, _
:= deref(recv
.typ
); t
!= Typ
[Invalid
] {
209 if T
, _
:= t
.(*Named
); T
!= nil {
210 // spec: "The type denoted by T is called the receiver base type; it must not
211 // be a pointer or interface type and it must be declared in the same package
213 if T
.obj
.pkg
!= check
.pkg
{
214 err
= "type not defined in this package"
216 // TODO(gri) This is not correct if the underlying type is unknown yet.
217 switch u
:= T
.underlying
.(type) {
219 // unsafe.Pointer is treated like a regular pointer
220 if u
.kind
== UnsafePointer
{
221 err
= "unsafe.Pointer"
223 case *Pointer
, *Interface
:
224 err
= "pointer or interface type"
228 err
= "basic or unnamed type"
231 check
.errorf(recv
.pos
, "invalid receiver %s (%s)", recv
.typ
, err
)
239 sig
.params
= NewTuple(params
...)
240 sig
.results
= NewTuple(results
...)
241 sig
.variadic
= variadic
244 // typExprInternal drives type checking of types.
245 // Must only be called by typExpr.
247 func (check
*Checker
) typExprInternal(e ast
.Expr
, def
*Named
, path
[]*TypeName
) Type
{
248 switch e
:= e
.(type) {
250 // ignore - error reported before
254 check
.ident(&x
, e
, def
, path
)
259 def
.setUnderlying(typ
)
262 // ignore - error reported before
264 check
.errorf(x
.pos(), "%s used as type", &x
)
266 check
.errorf(x
.pos(), "%s is not a type", &x
)
269 case *ast
.SelectorExpr
:
271 check
.selector(&x
, e
)
276 def
.setUnderlying(typ
)
279 // ignore - error reported before
281 check
.errorf(x
.pos(), "%s used as type", &x
)
283 check
.errorf(x
.pos(), "%s is not a type", &x
)
287 return check
.typExpr(e
.X
, def
, path
)
292 def
.setUnderlying(typ
)
293 typ
.len = check
.arrayLength(e
.Len
)
294 typ
.elem
= check
.typExpr(e
.Elt
, nil, path
)
299 def
.setUnderlying(typ
)
300 typ
.elem
= check
.typ(e
.Elt
)
304 case *ast
.StructType
:
306 def
.setUnderlying(typ
)
307 check
.structType(typ
, e
, path
)
312 def
.setUnderlying(typ
)
313 typ
.base
= check
.typ(e
.X
)
317 typ
:= new(Signature
)
318 def
.setUnderlying(typ
)
319 check
.funcType(typ
, nil, e
)
322 case *ast
.InterfaceType
:
323 typ
:= new(Interface
)
324 def
.setUnderlying(typ
)
325 check
.interfaceType(typ
, e
, def
, path
)
330 def
.setUnderlying(typ
)
332 typ
.key
= check
.typ(e
.Key
)
333 typ
.elem
= check
.typ(e
.Value
)
335 // spec: "The comparison operators == and != must be fully defined
336 // for operands of the key type; thus the key type must not be a
337 // function, map, or slice."
339 // Delay this check because it requires fully setup types;
340 // it is safe to continue in any case (was issue 6667).
342 if !Comparable(typ
.key
) {
343 check
.errorf(e
.Key
.Pos(), "invalid map key type %s", typ
.key
)
351 def
.setUnderlying(typ
)
355 case ast
.SEND | ast
.RECV
:
362 check
.invalidAST(e
.Pos(), "unknown channel direction %d", e
.Dir
)
367 typ
.elem
= check
.typ(e
.Value
)
371 check
.errorf(e
.Pos(), "%s is not a type", e
)
375 def
.setUnderlying(typ
)
379 // typeOrNil type-checks the type expression (or nil value) e
380 // and returns the typ of e, or nil.
381 // If e is neither a type nor nil, typOrNil returns Typ[Invalid].
383 func (check
*Checker
) typOrNil(e ast
.Expr
) Type
{
385 check
.rawExpr(&x
, e
, nil)
388 // ignore - error reported before
390 check
.errorf(x
.pos(), "%s used as type", &x
)
399 check
.errorf(x
.pos(), "%s is not a type", &x
)
404 // arrayLength type-checks the array length expression e
405 // and returns the constant length >= 0, or a value < 0
406 // to indicate an error (and thus an unknown length).
407 func (check
*Checker
) arrayLength(e ast
.Expr
) int64 {
410 if x
.mode
!= constant_
{
411 if x
.mode
!= invalid
{
412 check
.errorf(x
.pos(), "array length %s must be constant", &x
)
416 if isUntyped(x
.typ
) ||
isInteger(x
.typ
) {
417 if val
:= constant
.ToInt(x
.val
); val
.Kind() == constant
.Int
{
418 if representableConst(val
, check
.conf
, Typ
[Int
], nil) {
419 if n
, ok
:= constant
.Int64Val(val
); ok
&& n
>= 0 {
422 check
.errorf(x
.pos(), "invalid array length %s", &x
)
427 check
.errorf(x
.pos(), "array length %s must be integer", &x
)
431 func (check
*Checker
) collectParams(scope
*Scope
, list
*ast
.FieldList
, variadicOk
bool) (params
[]*Var
, variadic
bool) {
436 var named
, anonymous
bool
437 for i
, field
:= range list
.List
{
439 if t
, _
:= ftype
.(*ast
.Ellipsis
); t
!= nil {
441 if variadicOk
&& i
== len(list
.List
)-1 {
444 check
.invalidAST(field
.Pos(), "... not permitted")
445 // ignore ... and continue
448 typ
:= check
.typ(ftype
)
449 // The parser ensures that f.Tag is nil and we don't
450 // care if a constructed AST contains a non-nil tag.
451 if len(field
.Names
) > 0 {
453 for _
, name
:= range field
.Names
{
455 check
.invalidAST(name
.Pos(), "anonymous parameter")
458 par
:= NewParam(name
.Pos(), check
.pkg
, name
.Name
, typ
)
459 check
.declare(scope
, name
, par
, scope
.pos
)
460 params
= append(params
, par
)
464 // anonymous parameter
465 par
:= NewParam(ftype
.Pos(), check
.pkg
, "", typ
)
466 check
.recordImplicit(field
, par
)
467 params
= append(params
, par
)
472 if named
&& anonymous
{
473 check
.invalidAST(list
.Pos(), "list contains both named and anonymous parameters")
477 // For a variadic function, change the last parameter's type from T to []T.
478 if variadic
&& len(params
) > 0 {
479 last
:= params
[len(params
)-1]
480 last
.typ
= &Slice
{elem
: last
.typ
}
486 func (check
*Checker
) declareInSet(oset
*objset
, pos token
.Pos
, obj Object
) bool {
487 if alt
:= oset
.insert(obj
); alt
!= nil {
488 check
.errorf(pos
, "%s redeclared", obj
.Name())
489 check
.reportAltDecl(alt
)
495 func (check
*Checker
) interfaceType(ityp
*Interface
, iface
*ast
.InterfaceType
, def
*Named
, path
[]*TypeName
) {
496 // fast-track empty interface
497 if iface
.Methods
.List
== nil {
498 ityp
.allMethods
= markComplete
502 // collect embedded interfaces
503 // Only needed for printing and API. Delay collection
504 // to end of type-checking (for package-global interfaces)
505 // when all types are complete. Local interfaces are handled
506 // after each statement (as each statement processes delayed
508 interfaceContext
:= check
.context
// capture for use in closure below
511 check
.trace(iface
.Pos(), "-- delayed checking embedded interfaces of %v", iface
)
518 // The context must be restored since for local interfaces
519 // delayed functions are processed after each statement
520 // (was issue #24140).
521 defer func(ctxt context
) {
524 check
.context
= interfaceContext
526 for _
, f
:= range iface
.Methods
.List
{
527 if len(f
.Names
) == 0 {
528 typ
:= check
.typ(f
.Type
)
529 // typ should be a named type denoting an interface
530 // (the parser will make sure it's a named type but
531 // constructed ASTs may be wrong).
532 if typ
== Typ
[Invalid
] {
533 continue // error reported before
535 embed
, _
:= typ
.Underlying().(*Interface
)
537 check
.errorf(f
.Type
.Pos(), "%s is not an interface", typ
)
540 // Correct embedded interfaces must be complete -
541 // don't just assert, but report error since this
542 // used to be the underlying cause for issue #18395.
543 if embed
.allMethods
== nil {
544 check
.dump("%v: incomplete embedded interface %s", f
.Type
.Pos(), typ
)
548 ityp
.embeddeds
= append(ityp
.embeddeds
, typ
)
551 // sort to match NewInterface/NewInterface2
552 // TODO(gri) we may be able to switch to source order
553 sort
.Stable(byUniqueTypeName(ityp
.embeddeds
))
556 // compute method set
561 info
:= check
.infoFromTypeLit(check
.scope
, iface
, tname
, path
)
562 if info
== nil || info
== &emptyIfaceInfo
{
563 // error or empty interface - exit early
564 ityp
.allMethods
= markComplete
568 // use named receiver type if available (for better error messages)
569 var recvTyp Type
= ityp
575 var sigfix
[]*methodInfo
576 for i
, minfo
:= range info
.methods
{
579 name
:= minfo
.src
.Names
[0]
581 // Don't type-check signature yet - use an
582 // empty signature now and update it later.
583 // Since we know the receiver, set it up now
584 // (required to avoid crash in ptrRecv; see
585 // e.g. test case for issue 6638).
586 // TODO(gri) Consider marking methods signatures
587 // as incomplete, for better error messages. See
588 // also the T4 and T5 tests in testdata/cycles2.src.
589 sig
:= new(Signature
)
590 sig
.recv
= NewVar(pos
, check
.pkg
, "", recvTyp
)
591 fun
= NewFunc(pos
, check
.pkg
, name
.Name
, sig
)
593 check
.recordDef(name
, fun
)
594 sigfix
= append(sigfix
, minfo
)
597 if i
< info
.explicits
{
598 ityp
.methods
= append(ityp
.methods
, fun
)
600 ityp
.allMethods
= append(ityp
.allMethods
, fun
)
603 // fix signatures now that we have collected all methods
604 savedContext
:= check
.context
605 for _
, minfo
:= range sigfix
{
606 // (possibly embedded) methods must be type-checked within their scope and
607 // type-checking them must not affect the current context (was issue #23914)
608 check
.context
= context
{scope
: minfo
.scope
}
609 typ
:= check
.typ(minfo
.src
.Type
)
610 sig
, _
:= typ
.(*Signature
)
612 if typ
!= Typ
[Invalid
] {
613 check
.invalidAST(minfo
.src
.Type
.Pos(), "%s is not a method signature", typ
)
615 continue // keep method with empty method signature
617 // update signature, but keep recv that was set up before
618 old
:= minfo
.fun
.typ
.(*Signature
)
620 *old
= *sig
// update signature (don't replace pointer!)
622 check
.context
= savedContext
624 // sort to match NewInterface/NewInterface2
625 // TODO(gri) we may be able to switch to source order
626 sort
.Sort(byUniqueMethodName(ityp
.methods
))
628 if ityp
.allMethods
== nil {
629 ityp
.allMethods
= markComplete
631 sort
.Sort(byUniqueMethodName(ityp
.allMethods
))
635 // byUniqueTypeName named type lists can be sorted by their unique type names.
636 type byUniqueTypeName
[]Type
638 func (a byUniqueTypeName
) Len() int { return len(a
) }
639 func (a byUniqueTypeName
) Less(i
, j
int) bool { return sortName(a
[i
]) < sortName(a
[j
]) }
640 func (a byUniqueTypeName
) Swap(i
, j
int) { a
[i
], a
[j
] = a
[j
], a
[i
] }
642 func sortName(t Type
) string {
643 if named
, _
:= t
.(*Named
); named
!= nil {
644 return named
.obj
.Id()
649 // byUniqueMethodName method lists can be sorted by their unique method names.
650 type byUniqueMethodName
[]*Func
652 func (a byUniqueMethodName
) Len() int { return len(a
) }
653 func (a byUniqueMethodName
) Less(i
, j
int) bool { return a
[i
].Id() < a
[j
].Id() }
654 func (a byUniqueMethodName
) Swap(i
, j
int) { a
[i
], a
[j
] = a
[j
], a
[i
] }
656 func (check
*Checker
) tag(t
*ast
.BasicLit
) string {
658 if t
.Kind
== token
.STRING
{
659 if val
, err
:= strconv
.Unquote(t
.Value
); err
== nil {
663 check
.invalidAST(t
.Pos(), "incorrect tag syntax: %q", t
.Value
)
668 func (check
*Checker
) structType(styp
*Struct
, e
*ast
.StructType
, path
[]*TypeName
) {
674 // struct fields and tags
678 // for double-declaration checks
681 // current field typ and tag
684 add
:= func(ident
*ast
.Ident
, embedded
bool, pos token
.Pos
) {
685 if tag
!= "" && tags
== nil {
686 tags
= make([]string, len(fields
))
689 tags
= append(tags
, tag
)
693 fld
:= NewField(pos
, check
.pkg
, name
, typ
, embedded
)
694 // spec: "Within a struct, non-blank field names must be unique."
695 if name
== "_" || check
.declareInSet(&fset
, pos
, fld
) {
696 fields
= append(fields
, fld
)
697 check
.recordDef(ident
, fld
)
701 // addInvalid adds an embedded field of invalid type to the struct for
702 // fields with errors; this keeps the number of struct fields in sync
703 // with the source as long as the fields are _ or have different names
705 addInvalid
:= func(ident
*ast
.Ident
, pos token
.Pos
) {
708 add(ident
, true, pos
)
711 for _
, f
:= range list
.List
{
712 typ
= check
.typExpr(f
.Type
, nil, path
)
713 tag
= check
.tag(f
.Tag
)
714 if len(f
.Names
) > 0 {
716 for _
, name
:= range f
.Names
{
717 add(name
, false, name
.Pos())
721 // spec: "An embedded type must be specified as a type name T or as a pointer
722 // to a non-interface type name *T, and T itself may not be a pointer type."
724 name
:= embeddedFieldIdent(f
.Type
)
726 check
.invalidAST(pos
, "embedded field type %s has no name", f
.Type
)
727 name
= ast
.NewIdent("_")
729 addInvalid(name
, pos
)
732 t
, isPtr
:= deref(typ
)
733 // Because we have a name, typ must be of the form T or *T, where T is the name
734 // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
735 switch t
:= t
.Underlying().(type) {
737 if t
== Typ
[Invalid
] {
738 // error was reported before
739 addInvalid(name
, pos
)
743 // unsafe.Pointer is treated like a regular pointer
744 if t
.kind
== UnsafePointer
{
745 check
.errorf(pos
, "embedded field type cannot be unsafe.Pointer")
746 addInvalid(name
, pos
)
751 check
.errorf(pos
, "embedded field type cannot be a pointer")
752 addInvalid(name
, pos
)
757 check
.errorf(pos
, "embedded field type cannot be a pointer to an interface")
758 addInvalid(name
, pos
)
770 func embeddedFieldIdent(e ast
.Expr
) *ast
.Ident
{
771 switch e
:= e
.(type) {
775 // *T is valid, but **T is not
776 if _
, ok
:= e
.X
.(*ast
.StarExpr
); !ok
{
777 return embeddedFieldIdent(e
.X
)
779 case *ast
.SelectorExpr
:
782 return nil // invalid embedded field