]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: move validType code into its own file
authorRobert Griesemer <gri@golang.org>
Sat, 15 Jan 2022 01:01:43 +0000 (17:01 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 24 Jan 2022 21:27:13 +0000 (21:27 +0000)
The validType check is independent of the work of declaring objects.
Move it into a separate file for better separation of concerns and
code organization.

No other changes - this is purely a code move.

Preparation for fixing issue #48962.

Change-Id: Ib08db2d009c4890882d0978b278e965ca3078851
Reviewed-on: https://go-review.googlesource.com/c/go/+/378674
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>

src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/validtype.go [new file with mode: 0644]
src/go/types/decl.go
src/go/types/validtype.go [new file with mode: 0644]

index d61d2a8b0d98ad99a409b56d5afc8af30aba62ce..22cea584d449434ef620c0d9251e1821fca11c1b 100644 (file)
@@ -304,96 +304,6 @@ loop:
        return false
 }
 
-type typeInfo uint
-
-// validType verifies that the given type does not "expand" infinitely
-// 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 {
-       const (
-               unknown typeInfo = iota
-               marked
-               valid
-               invalid
-       )
-
-       switch t := typ.(type) {
-       case *Array:
-               return check.validType(t.elem, path)
-
-       case *Struct:
-               for _, f := range t.fields {
-                       if check.validType(f.typ, path) == invalid {
-                               return invalid
-                       }
-               }
-
-       case *Union:
-               for _, t := range t.terms {
-                       if check.validType(t.typ, path) == invalid {
-                               return invalid
-                       }
-               }
-
-       case *Interface:
-               for _, etyp := range t.embeddeds {
-                       if check.validType(etyp, path) == invalid {
-                               return invalid
-                       }
-               }
-
-       case *Named:
-               // If t is parameterized, we should be considering the instantiated (expanded)
-               // form of t, but in general we can't with this algorithm: if t is an invalid
-               // type it may be so because it infinitely expands through a type parameter.
-               // Instantiating such a type would lead to an infinite sequence of instantiations.
-               // In general, we need "type flow analysis" to recognize those cases.
-               // Example: type A[T any] struct{ x A[*T] } (issue #48951)
-               // In this algorithm we always only consider the original, uninstantiated type.
-               // This won't recognize some invalid cases with parameterized types, but it
-               // will terminate.
-               t = t.orig
-
-               // don't touch the type if it is from a different package or the Universe scope
-               // (doing so would lead to a race condition - was issue #35049)
-               if t.obj.pkg != check.pkg {
-                       return valid
-               }
-
-               // 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
-                       return invalid
-               }
-
-               switch t.info {
-               case unknown:
-                       t.info = marked
-                       t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
-               case marked:
-                       // cycle detected
-                       for i, tn := range path {
-                               if t.obj.pkg != check.pkg {
-                                       panic("type cycle via package-external type")
-                               }
-                               if tn == t.obj {
-                                       check.cycleError(path[i:])
-                                       t.info = invalid
-                                       t.underlying = Typ[Invalid]
-                                       return invalid
-                               }
-                       }
-                       panic("cycle start not found")
-               }
-               return t.info
-       }
-
-       return valid
-}
-
 // cycleError reports a declaration cycle starting with
 // the object in cycle that is "first" in the source.
 func (check *Checker) cycleError(cycle []Object) {
diff --git a/src/cmd/compile/internal/types2/validtype.go b/src/cmd/compile/internal/types2/validtype.go
new file mode 100644 (file)
index 0000000..24d65e2
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types2
+
+type typeInfo uint
+
+// validType verifies that the given type does not "expand" infinitely
+// 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 {
+       const (
+               unknown typeInfo = iota
+               marked
+               valid
+               invalid
+       )
+
+       switch t := typ.(type) {
+       case *Array:
+               return check.validType(t.elem, path)
+
+       case *Struct:
+               for _, f := range t.fields {
+                       if check.validType(f.typ, path) == invalid {
+                               return invalid
+                       }
+               }
+
+       case *Union:
+               for _, t := range t.terms {
+                       if check.validType(t.typ, path) == invalid {
+                               return invalid
+                       }
+               }
+
+       case *Interface:
+               for _, etyp := range t.embeddeds {
+                       if check.validType(etyp, path) == invalid {
+                               return invalid
+                       }
+               }
+
+       case *Named:
+               // If t is parameterized, we should be considering the instantiated (expanded)
+               // form of t, but in general we can't with this algorithm: if t is an invalid
+               // type it may be so because it infinitely expands through a type parameter.
+               // Instantiating such a type would lead to an infinite sequence of instantiations.
+               // In general, we need "type flow analysis" to recognize those cases.
+               // Example: type A[T any] struct{ x A[*T] } (issue #48951)
+               // In this algorithm we always only consider the original, uninstantiated type.
+               // This won't recognize some invalid cases with parameterized types, but it
+               // will terminate.
+               t = t.orig
+
+               // don't touch the type if it is from a different package or the Universe scope
+               // (doing so would lead to a race condition - was issue #35049)
+               if t.obj.pkg != check.pkg {
+                       return valid
+               }
+
+               // 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
+                       return invalid
+               }
+
+               switch t.info {
+               case unknown:
+                       t.info = marked
+                       t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
+               case marked:
+                       // cycle detected
+                       for i, tn := range path {
+                               if t.obj.pkg != check.pkg {
+                                       panic("type cycle via package-external type")
+                               }
+                               if tn == t.obj {
+                                       check.cycleError(path[i:])
+                                       t.info = invalid
+                                       t.underlying = Typ[Invalid]
+                                       return invalid
+                               }
+                       }
+                       panic("cycle start not found")
+               }
+               return t.info
+       }
+
+       return valid
+}
index 02af0d5f3ea2113978bb8aa3efeb0699d1a52f75..5b54465f18f81969f6eef1491f7fbeb07fc43582 100644 (file)
@@ -303,96 +303,6 @@ loop:
        return false
 }
 
-type typeInfo uint
-
-// validType verifies that the given type does not "expand" infinitely
-// 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 {
-       const (
-               unknown typeInfo = iota
-               marked
-               valid
-               invalid
-       )
-
-       switch t := typ.(type) {
-       case *Array:
-               return check.validType(t.elem, path)
-
-       case *Struct:
-               for _, f := range t.fields {
-                       if check.validType(f.typ, path) == invalid {
-                               return invalid
-                       }
-               }
-
-       case *Union:
-               for _, t := range t.terms {
-                       if check.validType(t.typ, path) == invalid {
-                               return invalid
-                       }
-               }
-
-       case *Interface:
-               for _, etyp := range t.embeddeds {
-                       if check.validType(etyp, path) == invalid {
-                               return invalid
-                       }
-               }
-
-       case *Named:
-               // If t is parameterized, we should be considering the instantiated (expanded)
-               // form of t, but in general we can't with this algorithm: if t is an invalid
-               // type it may be so because it infinitely expands through a type parameter.
-               // Instantiating such a type would lead to an infinite sequence of instantiations.
-               // In general, we need "type flow analysis" to recognize those cases.
-               // Example: type A[T any] struct{ x A[*T] } (issue #48951)
-               // In this algorithm we always only consider the original, uninstantiated type.
-               // This won't recognize some invalid cases with parameterized types, but it
-               // will terminate.
-               t = t.orig
-
-               // don't touch the type if it is from a different package or the Universe scope
-               // (doing so would lead to a race condition - was issue #35049)
-               if t.obj.pkg != check.pkg {
-                       return valid
-               }
-
-               // 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
-                       return invalid
-               }
-
-               switch t.info {
-               case unknown:
-                       t.info = marked
-                       t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
-               case marked:
-                       // cycle detected
-                       for i, tn := range path {
-                               if t.obj.pkg != check.pkg {
-                                       panic("type cycle via package-external type")
-                               }
-                               if tn == t.obj {
-                                       check.cycleError(path[i:])
-                                       t.info = invalid
-                                       t.underlying = Typ[Invalid]
-                                       return invalid
-                               }
-                       }
-                       panic("cycle start not found")
-               }
-               return t.info
-       }
-
-       return valid
-}
-
 // cycleError reports a declaration cycle starting with
 // the object in cycle that is "first" in the source.
 func (check *Checker) cycleError(cycle []Object) {
diff --git a/src/go/types/validtype.go b/src/go/types/validtype.go
new file mode 100644 (file)
index 0000000..8972a7a
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+type typeInfo uint
+
+// validType verifies that the given type does not "expand" infinitely
+// 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 {
+       const (
+               unknown typeInfo = iota
+               marked
+               valid
+               invalid
+       )
+
+       switch t := typ.(type) {
+       case *Array:
+               return check.validType(t.elem, path)
+
+       case *Struct:
+               for _, f := range t.fields {
+                       if check.validType(f.typ, path) == invalid {
+                               return invalid
+                       }
+               }
+
+       case *Union:
+               for _, t := range t.terms {
+                       if check.validType(t.typ, path) == invalid {
+                               return invalid
+                       }
+               }
+
+       case *Interface:
+               for _, etyp := range t.embeddeds {
+                       if check.validType(etyp, path) == invalid {
+                               return invalid
+                       }
+               }
+
+       case *Named:
+               // If t is parameterized, we should be considering the instantiated (expanded)
+               // form of t, but in general we can't with this algorithm: if t is an invalid
+               // type it may be so because it infinitely expands through a type parameter.
+               // Instantiating such a type would lead to an infinite sequence of instantiations.
+               // In general, we need "type flow analysis" to recognize those cases.
+               // Example: type A[T any] struct{ x A[*T] } (issue #48951)
+               // In this algorithm we always only consider the original, uninstantiated type.
+               // This won't recognize some invalid cases with parameterized types, but it
+               // will terminate.
+               t = t.orig
+
+               // don't touch the type if it is from a different package or the Universe scope
+               // (doing so would lead to a race condition - was issue #35049)
+               if t.obj.pkg != check.pkg {
+                       return valid
+               }
+
+               // 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
+                       return invalid
+               }
+
+               switch t.info {
+               case unknown:
+                       t.info = marked
+                       t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
+               case marked:
+                       // cycle detected
+                       for i, tn := range path {
+                               if t.obj.pkg != check.pkg {
+                                       panic("type cycle via package-external type")
+                               }
+                               if tn == t.obj {
+                                       check.cycleError(path[i:])
+                                       t.info = invalid
+                                       t.underlying = Typ[Invalid]
+                                       return invalid
+                               }
+                       }
+                       panic("cycle start not found")
+               }
+               return t.info
+       }
+
+       return valid
+}