Skip to content

Commit 1abc6b0

Browse files
author
Robert Griesemer
committed
go/types, types2: permit type cycles through type parameter lists
Issue #49439 was about a deadlock during type inference inside a type parameter list of a recursive constraint. As a remedy we disallowed recursive type parameter lists. In the meantime we have removed support for type inference for type arguments to generic types; the Go 1.18 generic release didn't support it. As a consequence, the fix for #49439, CL 361922, is probably not needed anymore: cycles through type parameter lists are ok. Fixes #68162. For #49439. Change-Id: Ie9deb3274914d428e8e45071cee5e68abf8afe9c Reviewed-on: https://go-review.googlesource.com/c/go/+/711420 Commit-Queue: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Mark Freeman <markfreeman@google.com> Reviewed-by: Robert Griesemer <gri@google.com> TryBot-Bypass: Robert Griesemer <gri@google.com>
1 parent 9fdd690 commit 1abc6b0

File tree

14 files changed

+64
-31
lines changed

14 files changed

+64
-31
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,12 @@ loop:
302302
}
303303
}
304304

305+
// Cycles through type parameter lists are ok (go.dev/issue/68162).
306+
// TODO(gri) if we are happy with this this, remove this flag and simplify code.
307+
if tparCycle {
308+
return true
309+
}
310+
305311
check.cycleError(cycle, firstInSrc(cycle))
306312
return false
307313
}

src/go/types/decl.go

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

306+
// Cycles through type parameter lists are ok (go.dev/issue/68162).
307+
// TODO(gri) if we are happy with this this, remove this flag and simplify code.
308+
if tparCycle {
309+
return true
310+
}
311+
306312
check.cycleError(cycle, firstInSrc(cycle))
307313
return false
308314
}

src/internal/types/testdata/fixedbugs/issue45550.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
package p
66

7-
type Builder /* ERROR "invalid recursive type" */ [T interface{ struct{ Builder[T] } }] struct{}
7+
type Builder[T ~struct{ Builder[T] }] struct{}
88
type myBuilder struct {
99
Builder[myBuilder]
1010
}

src/internal/types/testdata/fixedbugs/issue46461.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
package p
88

99
// test case 1
10-
type T /* ERROR "invalid recursive type" */ [U interface{ M() T[U] }] int
10+
type T[U interface{ M() T[U] }] int
1111

1212
type X int
1313

1414
func (X) M() T[X] { return 0 }
1515

1616
// test case 2
17-
type A /* ERROR "invalid recursive type" */ [T interface{ A[T] }] interface{}
17+
type A[T interface{ A[T] }] interface{}
1818

1919
// test case 3
20-
type A2 /* ERROR "invalid recursive type" */ [U interface{ A2[U] }] interface{ M() A2[U] }
20+
type A2[U interface{ A2[U] }] interface{ M() A2[U] }
2121

2222
type I interface{ A2[I]; M() A2[I] }

src/internal/types/testdata/fixedbugs/issue46461a.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77
package p
88

99
// test case 1
10-
type T /* ERROR "invalid recursive type" */ [U interface{ M() T[U] }] int
10+
type T[U interface{ M() T[U] }] int
1111

1212
type X int
1313

1414
func (X) M() T[X] { return 0 }
1515

1616
// test case 2
17-
type A /* ERROR "invalid recursive type" */ [T interface{ A[T] }] interface{}
17+
type A[T interface{ A[T] }] interface{}
1818

1919
// test case 3
20-
// TODO(gri) should report error only once
21-
type A2 /* ERROR "invalid recursive type" */ /* ERROR "invalid recursive type" */ [U interface{ A2[U] }] interface{ M() A2[U] }
20+
type A2[U interface{ A2[U] }] interface{ M() A2[U] }
2221

2322
type I interface{ A2[I]; M() A2[I] }

src/internal/types/testdata/fixedbugs/issue47796.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ package p
66

77
// parameterized types with self-recursive constraints
88
type (
9-
T1 /* ERROR "invalid recursive type" */ [P T1[P]] interface{}
10-
T2 /* ERROR "invalid recursive type" */ [P, Q T2[P, Q]] interface{}
9+
T1[P T1[P]] interface{}
10+
T2[P, Q T2[P, Q]] interface{}
1111
T3[P T2[P, Q], Q interface{ ~string }] interface{}
1212

13-
T4a /* ERROR "invalid recursive type" */ [P T4a[P]] interface{ ~int }
14-
T4b /* ERROR "invalid recursive type" */ [P T4b[int]] interface{ ~int }
15-
T4c /* ERROR "invalid recursive type" */ [P T4c[string]] interface{ ~int }
13+
T4a[P T4a[P]] interface{ ~int }
14+
T4b[P T4b[int]] interface{ ~int }
15+
T4c[P T4c[string /* ERROR "string does not satisfy T4c[string]" */]] interface{ ~int }
1616

1717
// mutually recursive constraints
18-
T5 /* ERROR "invalid recursive type" */ [P T6[P]] interface{ int }
18+
T5[P T6[P]] interface{ int }
1919
T6[P T5[P]] interface{ int }
2020
)
2121

@@ -28,6 +28,6 @@ var (
2828

2929
// test case from issue
3030

31-
type Eq /* ERROR "invalid recursive type" */ [a Eq[a]] interface {
31+
type Eq[a Eq[a]] interface {
3232
Equal(that a) bool
3333
}

src/internal/types/testdata/fixedbugs/issue48529.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
package p
66

7-
type T /* ERROR "invalid recursive type" */ [U interface{ M() T[U, int] }] int
7+
type T[U interface{ M() T /* ERROR "too many type arguments for type T" */ [U, int] }] int
88

99
type X int
1010

src/internal/types/testdata/fixedbugs/issue49439.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ package p
66

77
import "unsafe"
88

9-
type T0 /* ERROR "invalid recursive type" */ [P T0[P]] struct{}
9+
type T0[P T0[P]] struct{}
1010

11-
type T1 /* ERROR "invalid recursive type" */ [P T2[P]] struct{}
12-
type T2[P T1[P]] struct{}
11+
type T1[P T2[P /* ERROR "P does not satisfy T1[P]" */]] struct{}
12+
type T2[P T1[P /* ERROR "P does not satisfy T2[P]" */]] struct{}
1313

14-
type T3 /* ERROR "invalid recursive type" */ [P interface{ ~struct{ f T3[int] } }] struct{}
14+
type T3[P interface{ ~struct{ f T3[int /* ERROR "int does not satisfy" */ ] } }] struct{}
1515

1616
// valid cycle in M
1717
type N[P M[P]] struct{}
18-
type M[Q any] struct { F *M[Q] }
18+
type M[Q any] struct{ F *M[Q] }
1919

2020
// "crazy" case
2121
type TC[P [unsafe.Sizeof(func() {
22-
type T [P [unsafe.Sizeof(func(){})]byte] struct{}
22+
type T[P [unsafe.Sizeof(func() {})]byte] struct{}
2323
})]byte] struct{}
2424

2525
// test case from issue
26-
type X /* ERROR "invalid recursive type" */ [T any, PT X[T]] interface{}
26+
type X[T any, PT X /* ERROR "not enough type arguments for type X" */ [T]] interface{}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2024 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 main
6+
7+
type N[B N[B]] interface {
8+
Add(B) B
9+
}
10+
11+
func Add[P N[P]](x, y P) P {
12+
return x.Add(y)
13+
}
14+
15+
type MyInt int
16+
17+
func (x MyInt) Add(y MyInt) MyInt {
18+
return x + y
19+
}
20+
21+
func main() {
22+
var x, y MyInt = 2, 3
23+
println(Add(x, y))
24+
}

test/typeparam/issue46461.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// errorcheck
1+
// compile
22

33
// Copyright 2021 The Go Authors. All rights reserved.
44
// Use of this source code is governed by a BSD-style
55
// license that can be found in the LICENSE file.
66

77
package p
88

9-
type T[U interface{ M() T[U] }] int // ERROR "invalid recursive type: T refers to itself"
9+
type T[U interface{ M() T[U] }] int
1010

1111
type X int
1212

0 commit comments

Comments
 (0)