mirror of
https://github.com/golang/go
synced 2024-11-26 08:17:59 -07:00
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 <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
62cad233a6
commit
b3a5640397
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user