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.
7 // validType verifies that the given type does not "expand" indefinitely
8 // producing a cycle in the type graph. Cycles are detected by marking
10 // (Cycles involving alias types, as in "type A = [10]A" are detected
11 // earlier, via the objDecl cycle detection mechanism.)
12 func (check *Checker) validType(typ *Named) {
13 check.validType0(typ, nil)
18 func (check *Checker) validType0(typ Type, path []Object) typeInfo {
20 unknown typeInfo = iota
26 switch t := typ.(type) {
28 return check.validType0(t.elem, path)
31 for _, f := range t.fields {
32 if check.validType0(f.typ, path) == invalid {
38 for _, t := range t.terms {
39 if check.validType0(t.typ, path) == invalid {
45 for _, etyp := range t.embeddeds {
46 if check.validType0(etyp, path) == invalid {
52 // If t is parameterized, we should be considering the instantiated (expanded)
53 // form of t, but in general we can't with this algorithm: if t is an invalid
54 // type it may be so because it infinitely expands through a type parameter.
55 // Instantiating such a type would lead to an infinite sequence of instantiations.
56 // In general, we need "type flow analysis" to recognize those cases.
57 // Example: type A[T any] struct{ x A[*T] } (issue #48951)
58 // In this algorithm we always only consider the original, uninstantiated type.
59 // This won't recognize some invalid cases with parameterized types, but it
63 // don't report a 2nd error if we already know the type is invalid
64 // (e.g., if a cycle was detected earlier, via under).
65 if t.underlying == Typ[Invalid] {
66 check.infoMap[t] = invalid
70 switch check.infoMap[t] {
72 check.infoMap[t] = marked
73 check.infoMap[t] = check.validType0(t.fromRHS, append(path, t.obj))
76 for i, tn := range path {
77 // Even though validType now can hande cycles through external
78 // types, we can't have cycles through external types because
79 // no such types are detected yet.
80 // TODO(gri) Remove this check once we can detect such cycles,
81 // and adjust cycleError accordingly.
82 if t.obj.pkg != check.pkg {
83 panic("type cycle via package-external type")
86 check.cycleError(path[i:])
87 check.infoMap[t] = invalid
88 // don't modify imported types (leads to race condition, see #35049)
89 if t.obj.pkg == check.pkg {
90 t.underlying = Typ[Invalid]
95 panic("cycle start not found")
97 return check.infoMap[t]