]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: use a map instead of a field for marking in validType
authorRobert Griesemer <gri@golang.org>
Wed, 12 Jan 2022 23:54:15 +0000 (15:54 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 24 Jan 2022 21:27:18 +0000 (21:27 +0000)
With this change validType doesn't modify global state anymore.
It also eliminates the need for an extra field in each object.

Preparation for fixing issue #48962.

Change-Id: If241ec77ff48911d5b43d89adabfb8ef54452c6b
Reviewed-on: https://go-review.googlesource.com/c/go/+/378176
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

12 files changed:
src/cmd/compile/internal/types2/check.go
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/sizeof_test.go
src/cmd/compile/internal/types2/typexpr.go
src/cmd/compile/internal/types2/validtype.go
src/go/types/check.go
src/go/types/decl.go
src/go/types/named.go
src/go/types/sizeof_test.go
src/go/types/typexpr.go
src/go/types/validtype.go

index 22a921d0d78d45db48f2b3d0f0bc75f67ad897ac..cce324633eb28a197aeec4e746369be37bb603e8 100644 (file)
@@ -111,6 +111,7 @@ type Checker struct {
        nextID  uint64                 // unique Id for type parameters (first valid Id is 1)
        objMap  map[Object]*declInfo   // maps package-level objects and (non-interface) methods to declaration info
        impMap  map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
+       infoMap map[*Named]typeInfo    // maps named types to their associated type info (for cycle detection)
 
        // pkgPathMap maps package names to the set of distinct import paths we've
        // seen for that name, anywhere in the import graph. It is used for
@@ -221,6 +222,7 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
                version: version,
                objMap:  make(map[Object]*declInfo),
                impMap:  make(map[importKey]*Package),
+               infoMap: make(map[*Named]typeInfo),
        }
 }
 
index 22cea584d449434ef620c0d9251e1821fca11c1b..ab2983c80fbeba9e6975f7d7c46d67ac4ed5493c 100644 (file)
@@ -477,7 +477,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named
 
        var rhs Type
        check.later(func() {
-               check.validType(obj.typ, nil)
+               check.validType(obj.typ)
                // If typ is local, an error was already reported where typ is specified/defined.
                if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) {
                        check.versionErrorf(tdecl.Type, "go1.18", "using type constraint %s", rhs)
index c4217fa5080eb19471fc5686b9dcd055b9c5ef7d..834a25066b87b7d23cc9b5f8f6a74473360c05ac 100644 (file)
@@ -12,7 +12,6 @@ import (
 // A Named represents a named (defined) type.
 type Named struct {
        check      *Checker
-       info       typeInfo       // for cycle detection
        obj        *TypeName      // corresponding declared object for declared types; placeholder for instantiated types
        orig       *Named         // original, uninstantiated type
        fromRHS    Type           // type (on RHS of declaration) this *Named type is derived from (for cycle reporting)
index 8db2d60e8053947dfef387dc98caba0663cce707..52a1df1aa4a8241f198ff6d29ce986757ecf8a13 100644 (file)
@@ -31,7 +31,7 @@ func TestSizeof(t *testing.T) {
                {Interface{}, 44, 88},
                {Map{}, 16, 32},
                {Chan{}, 12, 24},
-               {Named{}, 68, 128},
+               {Named{}, 64, 120},
                {TypeParam{}, 28, 48},
                {term{}, 12, 24},
 
index 9121c2c1f64414bd0d45b205d39d3fa4bf44868a..580b53d3c7c30a6a67a2aee04b1c87b6fa429279 100644 (file)
@@ -487,7 +487,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
                        }
                }
 
-               check.validType(inst, nil)
+               check.validType(inst)
        })
 
        return inst
index 24d65e2c244d767f13304cec4f7a912bf50b61f9..9cb427b44d814e44d1803f4bf70bb070f4ba7d41 100644 (file)
@@ -4,14 +4,18 @@
 
 package types2
 
-type typeInfo uint
-
-// validType verifies that the given type does not "expand" infinitely
+// validType verifies that the given type does not "expand" indefinitely
 // producing a cycle in the type graph. Cycles are detected by marking
 // defined types.
 // (Cycles involving alias types, as in "type A = [10]A" are detected
 // earlier, via the objDecl cycle detection mechanism.)
-func (check *Checker) validType(typ Type, path []Object) typeInfo {
+func (check *Checker) validType(typ Type) {
+       check.validType0(typ, nil)
+}
+
+type typeInfo uint
+
+func (check *Checker) validType0(typ Type, path []Object) typeInfo {
        const (
                unknown typeInfo = iota
                marked
@@ -21,25 +25,25 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
 
        switch t := typ.(type) {
        case *Array:
-               return check.validType(t.elem, path)
+               return check.validType0(t.elem, path)
 
        case *Struct:
                for _, f := range t.fields {
-                       if check.validType(f.typ, path) == invalid {
+                       if check.validType0(f.typ, path) == invalid {
                                return invalid
                        }
                }
 
        case *Union:
                for _, t := range t.terms {
-                       if check.validType(t.typ, path) == invalid {
+                       if check.validType0(t.typ, path) == invalid {
                                return invalid
                        }
                }
 
        case *Interface:
                for _, etyp := range t.embeddeds {
-                       if check.validType(etyp, path) == invalid {
+                       if check.validType0(etyp, path) == invalid {
                                return invalid
                        }
                }
@@ -65,14 +69,14 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
                // don't report a 2nd error if we already know the type is invalid
                // (e.g., if a cycle was detected earlier, via under).
                if t.underlying == Typ[Invalid] {
-                       t.info = invalid
+                       check.infoMap[t] = invalid
                        return invalid
                }
 
-               switch t.info {
+               switch check.infoMap[t] {
                case unknown:
-                       t.info = marked
-                       t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
+                       check.infoMap[t] = marked
+                       check.infoMap[t] = check.validType0(t.fromRHS, append(path, t.obj)) // only types of current package added to path
                case marked:
                        // cycle detected
                        for i, tn := range path {
@@ -81,14 +85,14 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
                                }
                                if tn == t.obj {
                                        check.cycleError(path[i:])
-                                       t.info = invalid
+                                       check.infoMap[t] = invalid
                                        t.underlying = Typ[Invalid]
                                        return invalid
                                }
                        }
                        panic("cycle start not found")
                }
-               return t.info
+               return check.infoMap[t]
        }
 
        return valid
index bad4d5c9cd19b8e15aafd5238b1f1292a48283c3..90b46b807560abca4fef3e21f2b601195ae1fb44 100644 (file)
@@ -118,6 +118,7 @@ type Checker struct {
        nextID  uint64                 // unique Id for type parameters (first valid Id is 1)
        objMap  map[Object]*declInfo   // maps package-level objects and (non-interface) methods to declaration info
        impMap  map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
+       infoMap map[*Named]typeInfo    // maps named types to their associated type info (for cycle detection)
 
        // pkgPathMap maps package names to the set of distinct import paths we've
        // seen for that name, anywhere in the import graph. It is used for
@@ -229,6 +230,7 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
                version: version,
                objMap:  make(map[Object]*declInfo),
                impMap:  make(map[importKey]*Package),
+               infoMap: make(map[*Named]typeInfo),
        }
 }
 
index 5b54465f18f81969f6eef1491f7fbeb07fc43582..a9e89464f67118d12f14b47021b4aaebd423885d 100644 (file)
@@ -530,7 +530,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
 
        var rhs Type
        check.later(func() {
-               check.validType(obj.typ, nil)
+               check.validType(obj.typ)
                // If typ is local, an error was already reported where typ is specified/defined.
                if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) {
                        check.errorf(tdecl.Type, _UnsupportedFeature, "using type constraint %s requires go1.18 or later", rhs)
index a44686bc361ee71a3b9549e702a6fad5ee0adac5..6c77146485a9a5e29d8d1058cb5c8ec43d935b0c 100644 (file)
@@ -12,7 +12,6 @@ import (
 // A Named represents a named (defined) type.
 type Named struct {
        check      *Checker
-       info       typeInfo       // for cycle detection
        obj        *TypeName      // corresponding declared object for declared types; placeholder for instantiated types
        orig       *Named         // original, uninstantiated type
        fromRHS    Type           // type (on RHS of declaration) this *Named type is derived of (for cycle reporting)
index 24cbc2283957740c43e7576a2788cee8746f971c..b78099d0d04fb1ffe23c8527210f4f17075306e3 100644 (file)
@@ -30,7 +30,7 @@ func TestSizeof(t *testing.T) {
                {Interface{}, 44, 88},
                {Map{}, 16, 32},
                {Chan{}, 12, 24},
-               {Named{}, 68, 128},
+               {Named{}, 64, 120},
                {TypeParam{}, 28, 48},
                {term{}, 12, 24},
 
index b961f7c47fcc6df91ab49946903057156723c3fb..82de90b67a668a8f610ed5fa7c3c598cd2321adc 100644 (file)
@@ -472,7 +472,7 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re
                        }
                }
 
-               check.validType(inst, nil)
+               check.validType(inst)
        })
 
        return inst
index 8972a7ad85df871d2fe9a234f2b02e849afad5f5..d20a2b5bfaf3b19c8b2cd4effeaf09387328a1bc 100644 (file)
@@ -4,14 +4,18 @@
 
 package types
 
-type typeInfo uint
-
-// validType verifies that the given type does not "expand" infinitely
+// validType verifies that the given type does not "expand" indefinitely
 // producing a cycle in the type graph. Cycles are detected by marking
 // defined types.
 // (Cycles involving alias types, as in "type A = [10]A" are detected
 // earlier, via the objDecl cycle detection mechanism.)
-func (check *Checker) validType(typ Type, path []Object) typeInfo {
+func (check *Checker) validType(typ Type) {
+       check.validType0(typ, nil)
+}
+
+type typeInfo uint
+
+func (check *Checker) validType0(typ Type, path []Object) typeInfo {
        const (
                unknown typeInfo = iota
                marked
@@ -21,25 +25,25 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
 
        switch t := typ.(type) {
        case *Array:
-               return check.validType(t.elem, path)
+               return check.validType0(t.elem, path)
 
        case *Struct:
                for _, f := range t.fields {
-                       if check.validType(f.typ, path) == invalid {
+                       if check.validType0(f.typ, path) == invalid {
                                return invalid
                        }
                }
 
        case *Union:
                for _, t := range t.terms {
-                       if check.validType(t.typ, path) == invalid {
+                       if check.validType0(t.typ, path) == invalid {
                                return invalid
                        }
                }
 
        case *Interface:
                for _, etyp := range t.embeddeds {
-                       if check.validType(etyp, path) == invalid {
+                       if check.validType0(etyp, path) == invalid {
                                return invalid
                        }
                }
@@ -65,14 +69,14 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
                // don't report a 2nd error if we already know the type is invalid
                // (e.g., if a cycle was detected earlier, via under).
                if t.underlying == Typ[Invalid] {
-                       t.info = invalid
+                       check.infoMap[t] = invalid
                        return invalid
                }
 
-               switch t.info {
+               switch check.infoMap[t] {
                case unknown:
-                       t.info = marked
-                       t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
+                       check.infoMap[t] = marked
+                       check.infoMap[t] = check.validType0(t.fromRHS, append(path, t.obj)) // only types of current package added to path
                case marked:
                        // cycle detected
                        for i, tn := range path {
@@ -81,14 +85,14 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
                                }
                                if tn == t.obj {
                                        check.cycleError(path[i:])
-                                       t.info = invalid
+                                       check.infoMap[t] = invalid
                                        t.underlying = Typ[Invalid]
                                        return invalid
                                }
                        }
                        panic("cycle start not found")
                }
-               return t.info
+               return check.infoMap[t]
        }
 
        return valid