From b3a5640397e887514a860b9eb73e125c2b650f7b Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 8 Mar 2021 23:38:42 -0500 Subject: [PATCH] go/types: remove the concept of finals Checker.finals and the corresponding atEnd were added in CL 191418 as a mechanism to postpone interface type comparison until after all interfaces were complete. In the intervening CL 195837 we've adopted a convention of ensuring that interfaces are complete before comparing them. Since then we've also added the additional case of expansion for lazily resolving syntax. Checker.later defers resolution of types until points in the checking pass where all reachable types can be fully type checked, so the concept of finals should no longer be necessary. Change-Id: I58818c1a6b605dccc9b0ecb3a1f6859c138175d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/299590 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/check.go | 21 --------------------- src/go/types/typexpr.go | 12 ++++++------ 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/go/types/check.go b/src/go/types/check.go index 69e9466a8b9..b28481d7bd6 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -104,7 +104,6 @@ type Checker struct { methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods untyped map[ast.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 @@ -144,14 +143,6 @@ func (check *Checker) later(f func()) { 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) @@ -212,7 +203,6 @@ func (check *Checker) initFiles(files []*ast.File) { check.methods = nil check.untyped = nil check.delayed = nil - check.finals = nil // determine package name and collect valid files pkg := check.pkg @@ -269,7 +259,6 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.packageObjects() check.processDelayed(0) // incl. all functions - check.processFinals() check.initOrder() @@ -308,16 +297,6 @@ func (check *Checker) processDelayed(top int) { 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 diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index e6846545c63..5185c33fcbf 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -140,7 +140,7 @@ func (check *Checker) ordinaryType(pos positioner, typ Type) { // 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.Pos(), t) // TODO(gri) is this the correct position? if t.allTypes != nil { @@ -531,7 +531,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { // // 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 { @@ -635,7 +635,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targs []ast.Expr, def *Named) // 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) }) @@ -905,7 +905,7 @@ func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { // 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()) { check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented @@ -1119,7 +1119,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { embeddedTyp := typ embeddedPos := f.Type - check.atEnd(func() { + check.later(func() { t, isPtr := deref(embeddedTyp) switch t := optype(t).(type) { case *Basic: @@ -1177,7 +1177,7 @@ func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) [] // 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)