Skip to content

Commit 0328b4f

Browse files
committed
go/types, types2: move validType code into its own file
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 <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent b850f36 commit 0328b4f

File tree

4 files changed

+190
-180
lines changed

4 files changed

+190
-180
lines changed

src/cmd/compile/internal/types2/decl.go

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -304,96 +304,6 @@ loop:
304304
return false
305305
}
306306

307-
type typeInfo uint
308-
309-
// validType verifies that the given type does not "expand" infinitely
310-
// producing a cycle in the type graph. Cycles are detected by marking
311-
// defined types.
312-
// (Cycles involving alias types, as in "type A = [10]A" are detected
313-
// earlier, via the objDecl cycle detection mechanism.)
314-
func (check *Checker) validType(typ Type, path []Object) typeInfo {
315-
const (
316-
unknown typeInfo = iota
317-
marked
318-
valid
319-
invalid
320-
)
321-
322-
switch t := typ.(type) {
323-
case *Array:
324-
return check.validType(t.elem, path)
325-
326-
case *Struct:
327-
for _, f := range t.fields {
328-
if check.validType(f.typ, path) == invalid {
329-
return invalid
330-
}
331-
}
332-
333-
case *Union:
334-
for _, t := range t.terms {
335-
if check.validType(t.typ, path) == invalid {
336-
return invalid
337-
}
338-
}
339-
340-
case *Interface:
341-
for _, etyp := range t.embeddeds {
342-
if check.validType(etyp, path) == invalid {
343-
return invalid
344-
}
345-
}
346-
347-
case *Named:
348-
// If t is parameterized, we should be considering the instantiated (expanded)
349-
// form of t, but in general we can't with this algorithm: if t is an invalid
350-
// type it may be so because it infinitely expands through a type parameter.
351-
// Instantiating such a type would lead to an infinite sequence of instantiations.
352-
// In general, we need "type flow analysis" to recognize those cases.
353-
// Example: type A[T any] struct{ x A[*T] } (issue #48951)
354-
// In this algorithm we always only consider the original, uninstantiated type.
355-
// This won't recognize some invalid cases with parameterized types, but it
356-
// will terminate.
357-
t = t.orig
358-
359-
// don't touch the type if it is from a different package or the Universe scope
360-
// (doing so would lead to a race condition - was issue #35049)
361-
if t.obj.pkg != check.pkg {
362-
return valid
363-
}
364-
365-
// don't report a 2nd error if we already know the type is invalid
366-
// (e.g., if a cycle was detected earlier, via under).
367-
if t.underlying == Typ[Invalid] {
368-
t.info = invalid
369-
return invalid
370-
}
371-
372-
switch t.info {
373-
case unknown:
374-
t.info = marked
375-
t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
376-
case marked:
377-
// cycle detected
378-
for i, tn := range path {
379-
if t.obj.pkg != check.pkg {
380-
panic("type cycle via package-external type")
381-
}
382-
if tn == t.obj {
383-
check.cycleError(path[i:])
384-
t.info = invalid
385-
t.underlying = Typ[Invalid]
386-
return invalid
387-
}
388-
}
389-
panic("cycle start not found")
390-
}
391-
return t.info
392-
}
393-
394-
return valid
395-
}
396-
397307
// cycleError reports a declaration cycle starting with
398308
// the object in cycle that is "first" in the source.
399309
func (check *Checker) cycleError(cycle []Object) {
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package types2
6+
7+
type typeInfo uint
8+
9+
// validType verifies that the given type does not "expand" infinitely
10+
// producing a cycle in the type graph. Cycles are detected by marking
11+
// defined types.
12+
// (Cycles involving alias types, as in "type A = [10]A" are detected
13+
// earlier, via the objDecl cycle detection mechanism.)
14+
func (check *Checker) validType(typ Type, path []Object) typeInfo {
15+
const (
16+
unknown typeInfo = iota
17+
marked
18+
valid
19+
invalid
20+
)
21+
22+
switch t := typ.(type) {
23+
case *Array:
24+
return check.validType(t.elem, path)
25+
26+
case *Struct:
27+
for _, f := range t.fields {
28+
if check.validType(f.typ, path) == invalid {
29+
return invalid
30+
}
31+
}
32+
33+
case *Union:
34+
for _, t := range t.terms {
35+
if check.validType(t.typ, path) == invalid {
36+
return invalid
37+
}
38+
}
39+
40+
case *Interface:
41+
for _, etyp := range t.embeddeds {
42+
if check.validType(etyp, path) == invalid {
43+
return invalid
44+
}
45+
}
46+
47+
case *Named:
48+
// If t is parameterized, we should be considering the instantiated (expanded)
49+
// form of t, but in general we can't with this algorithm: if t is an invalid
50+
// type it may be so because it infinitely expands through a type parameter.
51+
// Instantiating such a type would lead to an infinite sequence of instantiations.
52+
// In general, we need "type flow analysis" to recognize those cases.
53+
// Example: type A[T any] struct{ x A[*T] } (issue #48951)
54+
// In this algorithm we always only consider the original, uninstantiated type.
55+
// This won't recognize some invalid cases with parameterized types, but it
56+
// will terminate.
57+
t = t.orig
58+
59+
// don't touch the type if it is from a different package or the Universe scope
60+
// (doing so would lead to a race condition - was issue #35049)
61+
if t.obj.pkg != check.pkg {
62+
return valid
63+
}
64+
65+
// don't report a 2nd error if we already know the type is invalid
66+
// (e.g., if a cycle was detected earlier, via under).
67+
if t.underlying == Typ[Invalid] {
68+
t.info = invalid
69+
return invalid
70+
}
71+
72+
switch t.info {
73+
case unknown:
74+
t.info = marked
75+
t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
76+
case marked:
77+
// cycle detected
78+
for i, tn := range path {
79+
if t.obj.pkg != check.pkg {
80+
panic("type cycle via package-external type")
81+
}
82+
if tn == t.obj {
83+
check.cycleError(path[i:])
84+
t.info = invalid
85+
t.underlying = Typ[Invalid]
86+
return invalid
87+
}
88+
}
89+
panic("cycle start not found")
90+
}
91+
return t.info
92+
}
93+
94+
return valid
95+
}

src/go/types/decl.go

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -303,96 +303,6 @@ loop:
303303
return false
304304
}
305305

306-
type typeInfo uint
307-
308-
// validType verifies that the given type does not "expand" infinitely
309-
// producing a cycle in the type graph. Cycles are detected by marking
310-
// defined types.
311-
// (Cycles involving alias types, as in "type A = [10]A" are detected
312-
// earlier, via the objDecl cycle detection mechanism.)
313-
func (check *Checker) validType(typ Type, path []Object) typeInfo {
314-
const (
315-
unknown typeInfo = iota
316-
marked
317-
valid
318-
invalid
319-
)
320-
321-
switch t := typ.(type) {
322-
case *Array:
323-
return check.validType(t.elem, path)
324-
325-
case *Struct:
326-
for _, f := range t.fields {
327-
if check.validType(f.typ, path) == invalid {
328-
return invalid
329-
}
330-
}
331-
332-
case *Union:
333-
for _, t := range t.terms {
334-
if check.validType(t.typ, path) == invalid {
335-
return invalid
336-
}
337-
}
338-
339-
case *Interface:
340-
for _, etyp := range t.embeddeds {
341-
if check.validType(etyp, path) == invalid {
342-
return invalid
343-
}
344-
}
345-
346-
case *Named:
347-
// If t is parameterized, we should be considering the instantiated (expanded)
348-
// form of t, but in general we can't with this algorithm: if t is an invalid
349-
// type it may be so because it infinitely expands through a type parameter.
350-
// Instantiating such a type would lead to an infinite sequence of instantiations.
351-
// In general, we need "type flow analysis" to recognize those cases.
352-
// Example: type A[T any] struct{ x A[*T] } (issue #48951)
353-
// In this algorithm we always only consider the original, uninstantiated type.
354-
// This won't recognize some invalid cases with parameterized types, but it
355-
// will terminate.
356-
t = t.orig
357-
358-
// don't touch the type if it is from a different package or the Universe scope
359-
// (doing so would lead to a race condition - was issue #35049)
360-
if t.obj.pkg != check.pkg {
361-
return valid
362-
}
363-
364-
// don't report a 2nd error if we already know the type is invalid
365-
// (e.g., if a cycle was detected earlier, via under).
366-
if t.underlying == Typ[Invalid] {
367-
t.info = invalid
368-
return invalid
369-
}
370-
371-
switch t.info {
372-
case unknown:
373-
t.info = marked
374-
t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
375-
case marked:
376-
// cycle detected
377-
for i, tn := range path {
378-
if t.obj.pkg != check.pkg {
379-
panic("type cycle via package-external type")
380-
}
381-
if tn == t.obj {
382-
check.cycleError(path[i:])
383-
t.info = invalid
384-
t.underlying = Typ[Invalid]
385-
return invalid
386-
}
387-
}
388-
panic("cycle start not found")
389-
}
390-
return t.info
391-
}
392-
393-
return valid
394-
}
395-
396306
// cycleError reports a declaration cycle starting with
397307
// the object in cycle that is "first" in the source.
398308
func (check *Checker) cycleError(cycle []Object) {

src/go/types/validtype.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package types
6+
7+
type typeInfo uint
8+
9+
// validType verifies that the given type does not "expand" infinitely
10+
// producing a cycle in the type graph. Cycles are detected by marking
11+
// defined types.
12+
// (Cycles involving alias types, as in "type A = [10]A" are detected
13+
// earlier, via the objDecl cycle detection mechanism.)
14+
func (check *Checker) validType(typ Type, path []Object) typeInfo {
15+
const (
16+
unknown typeInfo = iota
17+
marked
18+
valid
19+
invalid
20+
)
21+
22+
switch t := typ.(type) {
23+
case *Array:
24+
return check.validType(t.elem, path)
25+
26+
case *Struct:
27+
for _, f := range t.fields {
28+
if check.validType(f.typ, path) == invalid {
29+
return invalid
30+
}
31+
}
32+
33+
case *Union:
34+
for _, t := range t.terms {
35+
if check.validType(t.typ, path) == invalid {
36+
return invalid
37+
}
38+
}
39+
40+
case *Interface:
41+
for _, etyp := range t.embeddeds {
42+
if check.validType(etyp, path) == invalid {
43+
return invalid
44+
}
45+
}
46+
47+
case *Named:
48+
// If t is parameterized, we should be considering the instantiated (expanded)
49+
// form of t, but in general we can't with this algorithm: if t is an invalid
50+
// type it may be so because it infinitely expands through a type parameter.
51+
// Instantiating such a type would lead to an infinite sequence of instantiations.
52+
// In general, we need "type flow analysis" to recognize those cases.
53+
// Example: type A[T any] struct{ x A[*T] } (issue #48951)
54+
// In this algorithm we always only consider the original, uninstantiated type.
55+
// This won't recognize some invalid cases with parameterized types, but it
56+
// will terminate.
57+
t = t.orig
58+
59+
// don't touch the type if it is from a different package or the Universe scope
60+
// (doing so would lead to a race condition - was issue #35049)
61+
if t.obj.pkg != check.pkg {
62+
return valid
63+
}
64+
65+
// don't report a 2nd error if we already know the type is invalid
66+
// (e.g., if a cycle was detected earlier, via under).
67+
if t.underlying == Typ[Invalid] {
68+
t.info = invalid
69+
return invalid
70+
}
71+
72+
switch t.info {
73+
case unknown:
74+
t.info = marked
75+
t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
76+
case marked:
77+
// cycle detected
78+
for i, tn := range path {
79+
if t.obj.pkg != check.pkg {
80+
panic("type cycle via package-external type")
81+
}
82+
if tn == t.obj {
83+
check.cycleError(path[i:])
84+
t.info = invalid
85+
t.underlying = Typ[Invalid]
86+
return invalid
87+
}
88+
}
89+
panic("cycle start not found")
90+
}
91+
return t.info
92+
}
93+
94+
return valid
95+
}

0 commit comments

Comments
 (0)