]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: permit type cycles through type parameter lists
authorRobert Griesemer <gri@google.com>
Mon, 13 Oct 2025 19:47:42 +0000 (12:47 -0700)
committerRobert Griesemer <gri@google.com>
Mon, 13 Oct 2025 21:27:13 +0000 (14:27 -0700)
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>

14 files changed:
src/cmd/compile/internal/types2/decl.go
src/go/types/decl.go
src/internal/types/testdata/fixedbugs/issue45550.go
src/internal/types/testdata/fixedbugs/issue46461.go
src/internal/types/testdata/fixedbugs/issue46461a.go
src/internal/types/testdata/fixedbugs/issue47796.go
src/internal/types/testdata/fixedbugs/issue48529.go
src/internal/types/testdata/fixedbugs/issue49439.go
src/internal/types/testdata/fixedbugs/issue68162.go [new file with mode: 0644]
test/typeparam/issue46461.go
test/typeparam/issue46461b.dir/a.go
test/typeparam/issue46461b.dir/b.go
test/typeparam/issue48280.dir/a.go
test/typeparam/issue48306.dir/a.go

index 34105816a65af3ad00b1fa8ec1161d164643195a..3ff24269669a941fb29d625d85b42db00bb1aa5d 100644 (file)
@@ -302,6 +302,12 @@ loop:
                }
        }
 
+       // Cycles through type parameter lists are ok (go.dev/issue/68162).
+       // TODO(gri) if we are happy with this this, remove this flag and simplify code.
+       if tparCycle {
+               return true
+       }
+
        check.cycleError(cycle, firstInSrc(cycle))
        return false
 }
index 42423d291cee8da4e01744270c60a1b1dec4fd62..fcae1f95295a676d0b8f51c06dc59d46d3902d0b 100644 (file)
@@ -303,6 +303,12 @@ loop:
                }
        }
 
+       // Cycles through type parameter lists are ok (go.dev/issue/68162).
+       // TODO(gri) if we are happy with this this, remove this flag and simplify code.
+       if tparCycle {
+               return true
+       }
+
        check.cycleError(cycle, firstInSrc(cycle))
        return false
 }
index 2ea4ffe3079540a0588bc14cf806f418b788b2a0..32fdde6740c7a55cf3893115fb8abe9386183ff9 100644 (file)
@@ -4,7 +4,7 @@
 
 package p
 
-type Builder /* ERROR "invalid recursive type" */ [T interface{ struct{ Builder[T] } }] struct{}
+type Builder[T ~struct{ Builder[T] }] struct{}
 type myBuilder struct {
        Builder[myBuilder]
 }
index e823013f9951676daabe94e76ed63db2b9c5482a..454f7e836537c6c533509e6b8bdbc84daa5b93b9 100644 (file)
@@ -7,16 +7,16 @@
 package p
 
 // test case 1
-type T /* ERROR "invalid recursive type" */ [U interface{ M() T[U] }] int
+type T[U interface{ M() T[U] }] int
 
 type X int
 
 func (X) M() T[X] { return 0 }
 
 // test case 2
-type A /* ERROR "invalid recursive type" */ [T interface{ A[T] }] interface{}
+type A[T interface{ A[T] }] interface{}
 
 // test case 3
-type A2 /* ERROR "invalid recursive type" */ [U interface{ A2[U] }] interface{ M() A2[U] }
+type A2[U interface{ A2[U] }] interface{ M() A2[U] }
 
 type I interface{ A2[I]; M() A2[I] }
index e4b8e1a240a973f62ed89669f3b1a8babe9376c0..74ed6c4882719cc65be11157c540f68ff3550f8d 100644 (file)
@@ -7,17 +7,16 @@
 package p
 
 // test case 1
-type T /* ERROR "invalid recursive type" */ [U interface{ M() T[U] }] int
+type T[U interface{ M() T[U] }] int
 
 type X int
 
 func (X) M() T[X] { return 0 }
 
 // test case 2
-type A /* ERROR "invalid recursive type" */ [T interface{ A[T] }] interface{}
+type A[T interface{ A[T] }] interface{}
 
 // test case 3
-// TODO(gri) should report error only once
-type A2 /* ERROR "invalid recursive type" */ /* ERROR "invalid recursive type" */ [U interface{ A2[U] }] interface{ M() A2[U] }
+type A2[U interface{ A2[U] }] interface{ M() A2[U] }
 
 type I interface{ A2[I]; M() A2[I] }
index 7f719ff6745eaa15adb84398befcfad945c92fce..b07cdddababf67b55ca7587f628e2f32283a12bd 100644 (file)
@@ -6,16 +6,16 @@ package p
 
 // parameterized types with self-recursive constraints
 type (
-       T1 /* ERROR "invalid recursive type" */ [P T1[P]]                            interface{}
-       T2 /* ERROR "invalid recursive type" */ [P, Q T2[P, Q]]                      interface{}
+       T1[P T1[P]]                            interface{}
+       T2[P, Q T2[P, Q]]                      interface{}
        T3[P T2[P, Q], Q interface{ ~string }] interface{}
 
-       T4a /* ERROR "invalid recursive type" */ [P T4a[P]]                                                        interface{ ~int }
-       T4b /* ERROR "invalid recursive type" */ [P T4b[int]]                                                      interface{ ~int }
-       T4c /* ERROR "invalid recursive type" */ [P T4c[string]] interface{ ~int }
+       T4a[P T4a[P]]                                                        interface{ ~int }
+       T4b[P T4b[int]]                                                      interface{ ~int }
+       T4c[P T4c[string /* ERROR "string does not satisfy T4c[string]" */]] interface{ ~int }
 
        // mutually recursive constraints
-       T5 /* ERROR "invalid recursive type" */ [P T6[P]] interface{ int }
+       T5[P T6[P]] interface{ int }
        T6[P T5[P]] interface{ int }
 )
 
@@ -28,6 +28,6 @@ var (
 
 // test case from issue
 
-type Eq /* ERROR "invalid recursive type" */ [a Eq[a]] interface {
+type Eq[a Eq[a]] interface {
        Equal(that a) bool
 }
index bcc5e3536d3457558fd2adc8d08fb2766412f2a1..eca1da89232b08bf399f2e659fd4509d5263ec8f 100644 (file)
@@ -4,7 +4,7 @@
 
 package p
 
-type T /* ERROR "invalid recursive type" */ [U interface{ M() T[U, int] }] int
+type T[U interface{ M() T /* ERROR "too many type arguments for type T" */ [U, int] }] int
 
 type X int
 
index 3852f160948913888f4bce28f7a28cc3dc89d549..63bedf61911914f99de3b34d555f8dcfd77387b8 100644 (file)
@@ -6,21 +6,21 @@ package p
 
 import "unsafe"
 
-type T0 /* ERROR "invalid recursive type" */ [P T0[P]] struct{}
+type T0[P T0[P]] struct{}
 
-type T1 /* ERROR "invalid recursive type" */ [P T2[P]] struct{}
-type T2[P T1[P]] struct{}
+type T1[P T2[P /* ERROR "P does not satisfy T1[P]" */]] struct{}
+type T2[P T1[P /* ERROR "P does not satisfy T2[P]" */]] struct{}
 
-type T3 /* ERROR "invalid recursive type" */ [P interface{ ~struct{ f T3[int] } }] struct{}
+type T3[P interface{ ~struct{ f T3[int /* ERROR "int does not satisfy" */ ] } }] struct{}
 
 // valid cycle in M
 type N[P M[P]] struct{}
-type M[Q any] struct { F *M[Q] }
+type M[Q any] struct{ F *M[Q] }
 
 // "crazy" case
 type TC[P [unsafe.Sizeof(func() {
-        type T [P [unsafe.Sizeof(func(){})]byte] struct{}
+       type T[P [unsafe.Sizeof(func() {})]byte] struct{}
 })]byte] struct{}
 
 // test case from issue
-type X /* ERROR "invalid recursive type" */ [T any, PT X[T]] interface{}
+type X[T any, PT X /* ERROR "not enough type arguments for type X" */ [T]] interface{}
diff --git a/src/internal/types/testdata/fixedbugs/issue68162.go b/src/internal/types/testdata/fixedbugs/issue68162.go
new file mode 100644 (file)
index 0000000..8efd8a6
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2024 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 main
+
+type N[B N[B]] interface {
+       Add(B) B
+}
+
+func Add[P N[P]](x, y P) P {
+       return x.Add(y)
+}
+
+type MyInt int
+
+func (x MyInt) Add(y MyInt) MyInt {
+       return x + y
+}
+
+func main() {
+       var x, y MyInt = 2, 3
+       println(Add(x, y))
+}
index 363a87cfe08f10ed145120369ab0a01fc7f13fee..7e35106c15b42e7fa5605c7ed1ccba005a239a36 100644 (file)
@@ -1,4 +1,4 @@
-// errorcheck
+// compile
 
 // Copyright 2021 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -6,7 +6,7 @@
 
 package p
 
-type T[U interface{ M() T[U] }] int // ERROR "invalid recursive type: T refers to itself"
+type T[U interface{ M() T[U] }] int
 
 type X int
 
index fcb414266d741c028cf82fd0ff2d7dff1ef5627b..0d53b3e20429cd571bac0e99208277c073872a46 100644 (file)
@@ -4,4 +4,4 @@
 
 package a
 
-type T[U interface{ M() int }] int
+type T[U interface{ M() T[U] }] int
index a4583257ffd657fbe1af1566cd6ad23babbc3e71..3393a375c2057091beae176a014282db2eac9d8e 100644 (file)
@@ -8,6 +8,4 @@ import "./a"
 
 type X int
 
-func (X) M() int { return 0 }
-
-type _ a.T[X]
+func (X) M() a.T[X] { return 0 }
index f66fd30e34ee432300fb932c332fc401818a65e6..17859e6aa902f0ad3627c0cf9e960188c560d392 100644 (file)
@@ -4,7 +4,7 @@
 
 package a
 
-type I[T any] interface {
+type I[T I[T]] interface {
        F() T
 }
 
index fdfd86cb6d4a5dc6390e936ccee80aa92531c6ad..739750b20b35e6abd472586c60c2399a3bbc8dda 100644 (file)
@@ -4,6 +4,6 @@
 
 package a
 
-type I[T any] interface {
+type I[T I[T]] interface {
        F() T
 }