]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: remove explicit path parameter from most type-checker functions (cleanup)
authorRobert Griesemer <gri@golang.org>
Tue, 21 Aug 2018 19:01:32 +0000 (12:01 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 30 Aug 2018 22:54:34 +0000 (22:54 +0000)
Now that most of the type-checker is using the object-coloring mechanism
to detect cycles, remove the explicit path parameter from the functions
that don't rely on it anymore.

Some of the syntactic-based resolver code (for aliases, interfaces)
still use an explicit path; leaving those unchanged for now.

The function cycle was moved from typexpr.go (where it is not used
anymore) to resolver.go (where it's still used). It has not changed.

Fixes #25773.

Change-Id: I2100adc8d66d5da9de9277dee94a1f08e5a88487
Reviewed-on: https://go-review.googlesource.com/130476
Reviewed-by: Alan Donovan <adonovan@google.com>
src/go/types/check.go
src/go/types/decl.go
src/go/types/expr.go
src/go/types/interfaces.go
src/go/types/resolver.go
src/go/types/typexpr.go

index 5b796be40d4c1da44972d5dfa0bd52e0495eafdb..91df94dcbc0dba96894c4e942a13828fe23deb50 100644 (file)
@@ -160,11 +160,6 @@ func (check *Checker) pop() Object {
        return obj
 }
 
-// pathString returns a string of the form a->b-> ... ->g for an object path [a, b, ... g].
-func (check *Checker) pathString() string {
-       return objPathString(check.objPath)
-}
-
 // NewChecker returns a new Checker instance for a given package.
 // Package files may be added incrementally via checker.Files.
 func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker {
index d845789143305388310e8b5074e970d08f4987ea..6eeec40ae661ef868c22cc93155811e285e86b56 100644 (file)
@@ -66,9 +66,9 @@ func objPathString(path []Object) string {
 
 // objDecl type-checks the declaration of obj in its respective (file) context.
 // See check.typ for the details on def and path.
-func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
+func (check *Checker) objDecl(obj Object, def *Named) {
        if trace {
-               check.trace(obj.Pos(), "-- checking %s %s (path = %s, objPath = %s)", obj.color(), obj, pathString(path), check.pathString())
+               check.trace(obj.Pos(), "-- checking %s %s (objPath = %s)", obj.color(), obj, objPathString(check.objPath))
                check.indent++
                defer func() {
                        check.indent--
@@ -237,7 +237,7 @@ func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
                check.varDecl(obj, d.lhs, d.typ, d.init)
        case *TypeName:
                // invalid recursive types are detected via path
-               check.typeDecl(obj, d.typ, def, path, d.alias)
+               check.typeDecl(obj, d.typ, def, d.alias)
        case *Func:
                // functions may be recursive - no need to track dependencies
                check.funcDecl(obj, d)
@@ -388,7 +388,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
 
        // determine type, if any
        if typ != nil {
-               t := check.typExpr(typ, nil, nil)
+               t := check.typExpr(typ, nil)
                if !isConstType(t) {
                        // don't report an error if the type is an invalid C (defined) type
                        // (issue #22090)
@@ -414,7 +414,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
 
        // determine type, if any
        if typ != nil {
-               obj.typ = check.typExpr(typ, nil, nil)
+               obj.typ = check.typExpr(typ, nil)
                // We cannot spread the type to all lhs variables if there
                // are more than one since that would mark them as checked
                // (see Checker.objDecl) and the assignment of init exprs,
@@ -489,13 +489,13 @@ func (n *Named) setUnderlying(typ Type) {
        }
 }
 
-func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName, alias bool) {
+func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bool) {
        assert(obj.typ == nil)
 
        if alias {
 
                obj.typ = Typ[Invalid]
-               obj.typ = check.typExpr(typ, nil, append(path, obj))
+               obj.typ = check.typExpr(typ, nil)
 
        } else {
 
@@ -504,7 +504,7 @@ func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*
                obj.typ = named // make sure recursive type declarations terminate
 
                // determine underlying type of named
-               check.typExpr(typ, named, append(path, obj))
+               check.typExpr(typ, named)
 
                // The underlying type of named may be itself a named type that is
                // incomplete:
@@ -594,7 +594,7 @@ func (check *Checker) addMethodDecls(obj *TypeName) {
                }
 
                // type-check
-               check.objDecl(m, nil, nil)
+               check.objDecl(m, nil)
 
                if base != nil {
                        base.methods = append(base.methods, m)
@@ -745,7 +745,7 @@ func (check *Checker) declStmt(decl ast.Decl) {
                                check.declare(check.scope, s.Name, obj, scopePos)
                                // mark and unmark type before calling typeDecl; its type is still nil (see Checker.objDecl)
                                obj.setColor(grey + color(check.push(obj)))
-                               check.typeDecl(obj, s.Type, nil, nil, s.Assign.IsValid())
+                               check.typeDecl(obj, s.Type, nil, s.Assign.IsValid())
                                check.pop().setColor(black)
                        default:
                                check.invalidAST(s.Pos(), "const, type, or var declaration expected")
index 143a9581822cee24add304c8c3a5fde7486e5113..3feb67ee1900f72233c81dc6e63e0735f10b5c52 100644 (file)
@@ -1010,7 +1010,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                goto Error // error was reported before
 
        case *ast.Ident:
-               check.ident(x, e, nil, nil)
+               check.ident(x, e, nil)
 
        case *ast.Ellipsis:
                // ellipses are handled explicitly where they are legal
@@ -1064,7 +1064,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                                        break
                                }
                        }
-                       typ = check.typExpr(e.Type, nil, nil)
+                       typ = check.typExpr(e.Type, nil)
                        base = typ
 
                case hint != nil:
@@ -1439,7 +1439,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        check.invalidAST(e.Pos(), "use of .(type) outside type switch")
                        goto Error
                }
-               T := check.typExpr(e.Type, nil, nil)
+               T := check.typExpr(e.Type, nil)
                if T == Typ[Invalid] {
                        goto Error
                }
index e4b42dc5a36b9cecf55fbba727a167ed9dc99e45..57dc1bccdcc5877d3403e0dc640c17c70fbd3155 100644 (file)
@@ -144,7 +144,7 @@ func (check *Checker) infoFromTypeLit(scope *Scope, iface *ast.InterfaceType, tn
        }
 
        if trace {
-               check.trace(iface.Pos(), "-- collect methods for %v (path = %s, objPath = %s)", iface, pathString(path), check.pathString())
+               check.trace(iface.Pos(), "-- collect methods for %v (path = %s, objPath = %s)", iface, pathString(path), objPathString(check.objPath))
                check.indent++
                defer func() {
                        check.indent--
index a462912cd149caed272ddf60bdb448eaf7e1b6d1..ec7e4ed1c594452f813609194d8f6cb891647284 100644 (file)
@@ -521,6 +521,26 @@ func (check *Checker) resolveBaseTypeName(name *ast.Ident) *TypeName {
        }
 }
 
+// cycle reports whether obj appears in path or not.
+// If it does, and report is set, it also reports a cycle error.
+func (check *Checker) cycle(obj *TypeName, path []*TypeName, report bool) bool {
+       // (it's ok to iterate forward because each named type appears at most once in path)
+       for i, prev := range path {
+               if prev == obj {
+                       if report {
+                               check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
+                               // print cycle
+                               for _, obj := range path[i:] {
+                                       check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
+                               }
+                               check.errorf(obj.Pos(), "\t%s", obj.Name())
+                       }
+                       return true
+               }
+       }
+       return false
+}
+
 // packageObjects typechecks all package objects, but not function bodies.
 func (check *Checker) packageObjects() {
        // process package objects in source order for reproducible results
@@ -539,11 +559,8 @@ func (check *Checker) packageObjects() {
                }
        }
 
-       // pre-allocate space for type declaration paths so that the underlying array is reused
-       typePath := make([]*TypeName, 0, 8)
-
        for _, obj := range objList {
-               check.objDecl(obj, nil, typePath)
+               check.objDecl(obj, nil)
        }
 
        // At this point we may have a non-empty check.methods map; this means that not all
index 1da1f01956f8600f09fe413d11d3f75d80a0b5fe..3ab4702f74ea211048374174c96d1451a4222c88 100644 (file)
@@ -16,9 +16,9 @@ import (
 
 // ident type-checks identifier e and initializes x with the value or type of e.
 // If an error occurred, x.mode is set to invalid.
-// For the meaning of def and path, see check.typ, below.
+// For the meaning of def, see check.typExpr, below.
 //
-func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeName) {
+func (check *Checker) ident(x *operand, e *ast.Ident, def *Named) {
        x.mode = invalid
        x.expr = e
 
@@ -35,7 +35,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
        }
        check.recordUse(e, obj)
 
-       check.objDecl(obj, def, path)
+       check.objDecl(obj, def)
        typ := obj.Type()
        assert(typ != nil)
 
@@ -103,37 +103,12 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
        x.typ = typ
 }
 
-// cycle reports whether obj appears in path or not.
-// If it does, and report is set, it also reports a cycle error.
-func (check *Checker) cycle(obj *TypeName, path []*TypeName, report bool) bool {
-       // (it's ok to iterate forward because each named type appears at most once in path)
-       for i, prev := range path {
-               if prev == obj {
-                       if report {
-                               check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
-                               // print cycle
-                               for _, obj := range path[i:] {
-                                       check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
-                               }
-                               check.errorf(obj.Pos(), "\t%s", obj.Name())
-                       }
-                       return true
-               }
-       }
-       return false
-}
-
 // typExpr type-checks the type expression e and returns its type, or Typ[Invalid].
 // If def != nil, e is the type specification for the named type def, declared
 // in a type declaration, and def.underlying will be set to the type of e before
-// any components of e are type-checked. Path contains the path of named types
-// referring to this type; i.e. it is the path of named types directly containing
-// each other and leading to the current type e. Indirect containment (e.g. via
-// pointer indirection, function parameter, etc.) breaks the path (leads to a new
-// path, and usually via calling Checker.typ below) and those types are not found
-// in the path.
+// any components of e are type-checked.
 //
-func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type) {
+func (check *Checker) typExpr(e ast.Expr, def *Named) (T Type) {
        if trace {
                check.trace(e.Pos(), "%s", e)
                check.indent++
@@ -143,7 +118,7 @@ func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type)
                }()
        }
 
-       T = check.typExprInternal(e, def, path)
+       T = check.typExprInternal(e, def)
        assert(isTyped(T))
        check.recordTypeAndValue(e, typexpr, T, nil)
 
@@ -156,11 +131,10 @@ func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type)
 // element types, etc. See the comment in typExpr for details.
 //
 func (check *Checker) typ(e ast.Expr) Type {
-       // typExpr is called with a nil path indicating an indirection:
-       // push indir sentinel on object path
+       // push indir sentinel on object path to indicate an indirection
        check.push(indir)
        defer check.pop()
-       return check.typExpr(e, nil, nil)
+       return check.typExpr(e, nil)
 }
 
 // funcType type-checks a function or method type.
@@ -231,14 +205,14 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
 // typExprInternal drives type checking of types.
 // Must only be called by typExpr.
 //
-func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName) Type {
+func (check *Checker) typExprInternal(e ast.Expr, def *Named) Type {
        switch e := e.(type) {
        case *ast.BadExpr:
                // ignore - error reported before
 
        case *ast.Ident:
                var x operand
-               check.ident(&x, e, def, path)
+               check.ident(&x, e, def)
 
                switch x.mode {
                case typexpr:
@@ -271,14 +245,14 @@ func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName)
                }
 
        case *ast.ParenExpr:
-               return check.typExpr(e.X, def, path)
+               return check.typExpr(e.X, def)
 
        case *ast.ArrayType:
                if e.Len != nil {
                        typ := new(Array)
                        def.setUnderlying(typ)
                        typ.len = check.arrayLength(e.Len)
-                       typ.elem = check.typExpr(e.Elt, nil, path)
+                       typ.elem = check.typExpr(e.Elt, nil)
                        return typ
 
                } else {
@@ -291,7 +265,7 @@ func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName)
        case *ast.StructType:
                typ := new(Struct)
                def.setUnderlying(typ)
-               check.structType(typ, e, path)
+               check.structType(typ, e)
                return typ
 
        case *ast.StarExpr:
@@ -309,7 +283,7 @@ func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName)
        case *ast.InterfaceType:
                typ := new(Interface)
                def.setUnderlying(typ)
-               check.interfaceType(typ, e, def, path)
+               check.interfaceType(typ, e, def)
                return typ
 
        case *ast.MapType:
@@ -479,7 +453,7 @@ func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool
        return true
 }
 
-func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named, path []*TypeName) {
+func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
        // fast-track empty interface
        if iface.Methods.List == nil {
                ityp.allMethods = markComplete
@@ -542,8 +516,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
 
        // compute method set
        var tname *TypeName
+       var path []*TypeName
        if def != nil {
                tname = def.obj
+               path = []*TypeName{tname}
        }
        info := check.infoFromTypeLit(check.scope, iface, tname, path)
        if info == nil || info == &emptyIfaceInfo {
@@ -652,7 +628,7 @@ func (check *Checker) tag(t *ast.BasicLit) string {
        return ""
 }
 
-func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeName) {
+func (check *Checker) structType(styp *Struct, e *ast.StructType) {
        list := e.Fields
        if list == nil {
                return
@@ -696,7 +672,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
        }
 
        for _, f := range list.List {
-               typ = check.typExpr(f.Type, nil, path)
+               typ = check.typExpr(f.Type, nil)
                tag = check.tag(f.Tag)
                if len(f.Names) > 0 {
                        // named fields