Skip to content

Commit fbdf830

Browse files
committed
go/types: avoid infinite expansion for invalid recursive generic types
This is a clean port of CL 355732 from types2 to go/types. Fixes #48951. Change-Id: I9f8cc0655166835d9450608f6e50b726659a73f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/355733 Trust: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent ad99d88 commit fbdf830

File tree

5 files changed

+44
-11
lines changed

5 files changed

+44
-11
lines changed

src/go/types/decl.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,17 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
329329
}
330330

331331
case *Named:
332-
t.resolve(check.conf.Context)
332+
// If t is parameterized, we should be considering the instantiated (expanded)
333+
// form of t, but in general we can't with this algorithm: if t is an invalid
334+
// type it may be so because it infinitely expands through a type parameter.
335+
// Instantiating such a type would lead to an infinite sequence of instantiations.
336+
// In general, we need "type flow analysis" to recognize those cases.
337+
// Example: type A[T any] struct{ x A[*T] } (issue #48951)
338+
// In this algorithm we always only consider the orginal, uninstantiated type.
339+
// This won't recognize some invalid cases with parameterized types, but it
340+
// will terminate.
341+
t = t.orig
342+
333343
// don't touch the type if it is from a different package or the Universe scope
334344
// (doing so would lead to a race condition - was issue #35049)
335345
if t.obj.pkg != check.pkg {
@@ -357,7 +367,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
357367
check.cycleError(path[i:])
358368
t.info = invalid
359369
t.underlying = Typ[Invalid]
360-
return t.info
370+
return invalid
361371
}
362372
}
363373
panic("cycle start not found")

src/go/types/testdata/check/issues.go2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ type List3[TElem any] struct {
146146
}
147147

148148
// Infinite generic type declarations must lead to an error.
149-
type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] }
150-
type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] }
149+
type inf1 /* ERROR illegal cycle */ [T any] struct{ _ inf1[T] }
150+
type inf2 /* ERROR illegal cycle */ [T any] struct{ inf2[T] }
151151

152152
// The implementation of conversions T(x) between integers and floating-point
153153
// numbers checks that both T and x have either integer or floating-point

src/go/types/testdata/fixedbugs/issue39634.go2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ func main7() { var _ foo7 = x7[int]{} }
3737
// func main8() {}
3838

3939
// crash 9
40-
type foo9[A any] interface { foo9 /* ERROR illegal cycle */ [A] }
41-
func _() { var _ = new(foo9 /* ERROR illegal cycle */ [int]) }
40+
type foo9 /* ERROR illegal cycle */ [A any] interface { foo9[A] }
41+
func _() { var _ = new(foo9[int]) }
4242

4343
// crash 12
4444
var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */

src/go/types/testdata/fixedbugs/issue39938.go2

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// license that can be found in the LICENSE file.
44

55
// Check "infinite expansion" cycle errors across instantiated types.
6+
// We can't detect these errors anymore at the moment. See #48962 for
7+
// details.
68

79
package p
810

@@ -11,19 +13,19 @@ type E1[P any] *P
1113
type E2[P any] struct{ _ P }
1214
type E3[P any] struct{ _ *P }
1315

14-
type T0 /* ERROR illegal cycle */ struct {
16+
type T0 /* illegal cycle */ struct {
1517
_ E0[T0]
1618
}
1719

18-
type T0_ /* ERROR illegal cycle */ struct {
20+
type T0_ /* illegal cycle */ struct {
1921
E0[T0_]
2022
}
2123

2224
type T1 struct {
2325
_ E1[T1]
2426
}
2527

26-
type T2 /* ERROR illegal cycle */ struct {
28+
type T2 /* illegal cycle */ struct {
2729
_ E2[T2]
2830
}
2931

@@ -33,15 +35,15 @@ type T3 struct {
3335

3436
// some more complex cases
3537

36-
type T4 /* ERROR illegal cycle */ struct {
38+
type T4 /* illegal cycle */ struct {
3739
_ E0[E2[T4]]
3840
}
3941

4042
type T5 struct {
4143
_ E0[E2[E0[E1[E2[[10]T5]]]]]
4244
}
4345

44-
type T6 /* ERROR illegal cycle */ struct {
46+
type T6 /* illegal cycle */ struct {
4547
_ E0[[10]E2[E0[E2[E2[T6]]]]]
4648
}
4749

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2020 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 p
6+
7+
type (
8+
A1 /* ERROR illegal cycle */ [P any] [10]A1[P]
9+
A2 /* ERROR illegal cycle */ [P any] [10]A2[*P]
10+
A3[P any] [10]*A3[P]
11+
12+
L1[P any] []L1[P]
13+
14+
S1 /* ERROR illegal cycle */ [P any] struct{ f S1[P] }
15+
S2 /* ERROR illegal cycle */ [P any] struct{ f S2[*P] } // like example in issue
16+
S3[P any] struct{ f *S3[P] }
17+
18+
I1 /* ERROR illegal cycle */ [P any] interface{ I1[P] }
19+
I2 /* ERROR illegal cycle */ [P any] interface{ I2[*P] }
20+
I3[P any] interface{ *I3 /* ERROR interface contains type constraints */ [P] }
21+
)

0 commit comments

Comments
 (0)