mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
9fdd6904da
commit
1abc6b0204
14 changed files with 64 additions and 31 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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] }
|
||||
|
|
|
|||
|
|
@ -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] }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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{}
|
||||
|
|
|
|||
24
src/internal/types/testdata/fixedbugs/issue68162.go
vendored
Normal file
24
src/internal/types/testdata/fixedbugs/issue68162.go
vendored
Normal file
|
|
@ -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))
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@
|
|||
|
||||
package a
|
||||
|
||||
type T[U interface{ M() int }] int
|
||||
type T[U interface{ M() T[U] }] int
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
package a
|
||||
|
||||
type I[T any] interface {
|
||||
type I[T I[T]] interface {
|
||||
F() T
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
package a
|
||||
|
||||
type I[T any] interface {
|
||||
type I[T I[T]] interface {
|
||||
F() T
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue