methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods
untyped map[syntax.Expr]exprInfo // map of expressions without final type
delayed []func() // stack of delayed action segments; segments are processed in FIFO order
- finals []func() // list of final actions; processed at the end of type-checking the current set of files
objPath []Object // path of object dependencies during type inference (for cycle reporting)
// context within which the current object is type-checked
check.delayed = append(check.delayed, f)
}
-// atEnd adds f to the list of actions processed at the end
-// of type-checking, before initialization order computation.
-// Actions added by atEnd are processed after any actions
-// added by later.
-func (check *Checker) atEnd(f func()) {
- check.finals = append(check.finals, f)
-}
-
// push pushes obj onto the object path and returns its index in the path.
func (check *Checker) push(obj Object) int {
check.objPath = append(check.objPath, obj)
check.methods = nil
check.untyped = nil
check.delayed = nil
- check.finals = nil
// determine package name and collect valid files
pkg := check.pkg
print("== processDelayed ==")
check.processDelayed(0) // incl. all functions
- check.processFinals()
print("== initOrder ==")
check.initOrder()
check.delayed = check.delayed[:top]
}
-func (check *Checker) processFinals() {
- n := len(check.finals)
- for _, f := range check.finals {
- f() // must not append to check.finals
- }
- if len(check.finals) != n {
- panic("internal error: final action list grew")
- }
-}
-
func (check *Checker) recordUntyped() {
if !debug && check.Types == nil {
return // nothing to do
// We don't want to call under() (via Interface) or complete interfaces while we
// are in the middle of type-checking parameter declarations that might belong to
// interface methods. Delay this check to the end of type-checking.
- check.atEnd(func() {
+ check.later(func() {
if t := asInterface(typ); t != nil {
check.completeInterface(pos, t) // TODO(gri) is this the correct position?
if t.allTypes != nil {
//
// Delay this check because it requires fully setup types;
// it is safe to continue in any case (was issue 6667).
- check.atEnd(func() {
+ check.later(func() {
if !Comparable(typ.key) {
var why string
if asTypeParam(typ.key) != nil {
// make sure we check instantiation works at least once
// and that the resulting type is valid
- check.atEnd(func() {
+ check.later(func() {
t := typ.expand()
check.validType(t, nil)
})
// If we're pre-go1.14 (overlapping embeddings are not permitted), report that
// error here as well (even though we could do it eagerly) because it's the same
// error message.
- check.atEnd(func() {
+ check.later(func() {
if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) {
var err error_
err.errorf(pos, "duplicate method %s", m.name)
// (via under(t)) a possibly incomplete type.
embeddedTyp := typ // for closure below
embeddedPos := pos
- check.atEnd(func() {
+ check.later(func() {
t, isPtr := deref(embeddedTyp)
switch t := optype(t).(type) {
case *Basic:
// interfaces, which may not be complete yet. It's ok to do this check at the
// end because it's not a requirement for correctness of the code.
// Note: This is a quadratic algorithm, but type lists tend to be short.
- check.atEnd(func() {
+ check.later(func() {
for i, t := range list {
if t := asInterface(t); t != nil {
check.completeInterface(types[i].Pos(), t)