mirror of
https://github.com/golang/go
synced 2024-11-11 23:20:24 -07:00
[dev.typeparams] cmd/compile/internal/types2: parameterized functions must have a body
Add the respective check and add missing bodies to tests. Use {} as body for functions that don't return a result. Use { panic(0) } as body for functions that return a result. For #47069. Change-Id: Ia5d7525c9c036baf8a955d13bff448401e08235e Reviewed-on: https://go-review.googlesource.com/c/go/+/340911 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
508624f359
commit
e4cfa2f6da
@ -329,10 +329,10 @@ func TestTypesInfo(t *testing.T) {
|
||||
{brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string]invalid type`},
|
||||
|
||||
// parameterized functions
|
||||
{genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`},
|
||||
{genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`},
|
||||
{genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`},
|
||||
{genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`},
|
||||
{genericPkg + `p0; func f[T any](T) {}; var _ = f[int]`, `f`, `func[generic_p0.T₁ interface{}](generic_p0.T₁)`},
|
||||
{genericPkg + `p1; func f[T any](T) {}; var _ = f[int]`, `f[int]`, `func(int)`},
|
||||
{genericPkg + `p2; func f[T any](T) {}; func _() { f(42) }`, `f`, `func[generic_p2.T₁ interface{}](generic_p2.T₁)`},
|
||||
{genericPkg + `p3; func f[T any](T) {}; func _() { f(42) }`, `f(42)`, `()`},
|
||||
|
||||
// type parameters
|
||||
{genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t
|
||||
@ -389,60 +389,60 @@ func TestInferredInfo(t *testing.T) {
|
||||
targs []string
|
||||
sig string
|
||||
}{
|
||||
{genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
|
||||
{genericPkg + `p0; func f[T any](T) {}; func _() { f(42) }`,
|
||||
`f`,
|
||||
[]string{`int`},
|
||||
`func(int)`,
|
||||
},
|
||||
{genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
|
||||
{genericPkg + `p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
|
||||
`f`,
|
||||
[]string{`rune`},
|
||||
`func(rune) rune`,
|
||||
},
|
||||
{genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
|
||||
{genericPkg + `p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
|
||||
`f`,
|
||||
[]string{`complex128`},
|
||||
`func(...complex128) complex128`,
|
||||
},
|
||||
{genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
|
||||
{genericPkg + `p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
|
||||
`f`,
|
||||
[]string{`float64`, `string`, `byte`},
|
||||
`func(float64, *string, []byte)`,
|
||||
},
|
||||
{genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
|
||||
{genericPkg + `p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
|
||||
`f`,
|
||||
[]string{`float64`, `byte`},
|
||||
`func(float64, *byte, ...[]byte)`,
|
||||
},
|
||||
|
||||
// we don't know how to translate these but we can type-check them
|
||||
{genericPkg + `q0; type T struct{}; func (T) m[P any](P); func _(x T) { x.m(42) }`,
|
||||
{genericPkg + `q0; type T struct{}; func (T) m[P any](P) {}; func _(x T) { x.m(42) }`,
|
||||
`x.m`,
|
||||
[]string{`int`},
|
||||
`func(int)`,
|
||||
},
|
||||
{genericPkg + `q1; type T struct{}; func (T) m[P any](P) P; func _(x T) { x.m(42) }`,
|
||||
{genericPkg + `q1; type T struct{}; func (T) m[P any](P) P { panic(0) }; func _(x T) { x.m(42) }`,
|
||||
`x.m`,
|
||||
[]string{`int`},
|
||||
`func(int) int`,
|
||||
},
|
||||
{genericPkg + `q2; type T struct{}; func (T) m[P any](...P) P; func _(x T) { x.m(42) }`,
|
||||
{genericPkg + `q2; type T struct{}; func (T) m[P any](...P) P { panic(0) }; func _(x T) { x.m(42) }`,
|
||||
`x.m`,
|
||||
[]string{`int`},
|
||||
`func(...int) int`,
|
||||
},
|
||||
{genericPkg + `q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C); func _(x T) { x.m(1.2, new(string), []byte{}) }`,
|
||||
{genericPkg + `q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C) {}; func _(x T) { x.m(1.2, new(string), []byte{}) }`,
|
||||
`x.m`,
|
||||
[]string{`float64`, `string`, `byte`},
|
||||
`func(float64, *string, []byte)`,
|
||||
},
|
||||
{genericPkg + `q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B); func _(x T) { x.m(1.2, new(byte)) }`,
|
||||
{genericPkg + `q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B) {}; func _(x T) { x.m(1.2, new(byte)) }`,
|
||||
`x.m`,
|
||||
[]string{`float64`, `byte`},
|
||||
`func(float64, *byte, ...[]byte)`,
|
||||
},
|
||||
|
||||
{genericPkg + `r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q); func _[P any](x T[P]) { x.m(42) }`,
|
||||
{genericPkg + `r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q) {}; func _[P any](x T[P]) { x.m(42) }`,
|
||||
`x.m`,
|
||||
[]string{`int`},
|
||||
`func(int)`,
|
||||
@ -454,38 +454,38 @@ func TestInferredInfo(t *testing.T) {
|
||||
// `func(float64)`,
|
||||
// },
|
||||
|
||||
{genericPkg + `s1; func f[T any, P interface{~*T}](x T); func _(x string) { f(x) }`,
|
||||
{genericPkg + `s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`,
|
||||
`f`,
|
||||
[]string{`string`, `*string`},
|
||||
`func(x string)`,
|
||||
},
|
||||
{genericPkg + `s2; func f[T any, P interface{~*T}](x []T); func _(x []int) { f(x) }`,
|
||||
{genericPkg + `s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`,
|
||||
`f`,
|
||||
[]string{`int`, `*int`},
|
||||
`func(x []int)`,
|
||||
},
|
||||
{genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
|
||||
{genericPkg + `s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
|
||||
`f`,
|
||||
[]string{`int`, `chan<- int`},
|
||||
`func(x []int)`,
|
||||
},
|
||||
{genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
|
||||
{genericPkg + `s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
|
||||
`f`,
|
||||
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
|
||||
`func(x []int)`,
|
||||
},
|
||||
|
||||
{genericPkg + `t1; func f[T any, P interface{~*T}]() T; func _() { _ = f[string] }`,
|
||||
{genericPkg + `t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`,
|
||||
`f`,
|
||||
[]string{`string`, `*string`},
|
||||
`func() string`,
|
||||
},
|
||||
{genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
|
||||
{genericPkg + `t2; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`,
|
||||
`f`,
|
||||
[]string{`int`, `chan<- int`},
|
||||
`func() []int`,
|
||||
},
|
||||
{genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
|
||||
{genericPkg + `t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
|
||||
`f`,
|
||||
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
|
||||
`func() []int`,
|
||||
|
@ -719,6 +719,10 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
|
||||
check.funcType(sig, fdecl.Recv, fdecl.TParamList, fdecl.Type)
|
||||
obj.color_ = saved
|
||||
|
||||
if len(fdecl.TParamList) > 0 && fdecl.Body == nil {
|
||||
check.softErrorf(fdecl, "parameterized function is missing function body")
|
||||
}
|
||||
|
||||
// function body must be type-checked after global declarations
|
||||
// (functions implemented elsewhere have no body)
|
||||
if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
|
||||
|
@ -40,7 +40,7 @@ func _[T interface{ m() }](x *T) {
|
||||
x.m /* ERROR x\.m undefined */ ()
|
||||
}
|
||||
|
||||
func f2[_ interface{ m1(); m2() }]()
|
||||
func f2[_ interface{ m1(); m2() }]() {}
|
||||
|
||||
type T struct{}
|
||||
func (T) m1()
|
||||
@ -232,7 +232,7 @@ func _[T interface{ ~func() }](f T) {
|
||||
|
||||
type sliceOf[E any] interface{ ~[]E }
|
||||
|
||||
func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S
|
||||
func append[T interface{}, S sliceOf[T], T2 interface{}](s S, t ...T2) S { panic(0) }
|
||||
|
||||
var f func()
|
||||
var cancelSlice []context.CancelFunc
|
||||
@ -240,7 +240,7 @@ var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](can
|
||||
|
||||
// A generic function must be instantiated with a type, not a value.
|
||||
|
||||
func g[T any](T) T
|
||||
func g[T any](T) T { panic(0) }
|
||||
|
||||
var _ = g[int]
|
||||
var _ = g[nil /* ERROR is not a type */ ]
|
||||
|
@ -114,7 +114,7 @@ func (it *Iterator[K, V]) Next() (K, V, bool) {
|
||||
|
||||
// chans
|
||||
|
||||
func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T])
|
||||
func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T]) { panic(0) }
|
||||
|
||||
// A sender is used to send values to a Receiver.
|
||||
type chans_Sender[T any] struct {
|
||||
|
@ -10,7 +10,7 @@ package p
|
||||
|
||||
type S struct{}
|
||||
|
||||
func (S) m[T any](v T)
|
||||
func (S) m[T any](v T) {}
|
||||
|
||||
// TODO(gri) Once we collect interface method type parameters
|
||||
// in the parser, we can enable these tests again.
|
||||
|
@ -23,7 +23,7 @@ type any interface{}
|
||||
// f1(int(0), int(0))
|
||||
// }
|
||||
|
||||
func f2[A any, B interface{~[]A}](A, B)
|
||||
func f2[A any, B interface{~[]A}](A, B) {}
|
||||
func _() {
|
||||
f := f2[byte]
|
||||
f(byte(0), []byte{})
|
||||
@ -39,7 +39,7 @@ func _() {
|
||||
// f3(x, &x, &x)
|
||||
// }
|
||||
|
||||
func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C)
|
||||
func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) {}
|
||||
func _() {
|
||||
f := f4[int]
|
||||
var x int
|
||||
@ -47,14 +47,14 @@ func _() {
|
||||
f4(x, []*int{}, &x)
|
||||
}
|
||||
|
||||
func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A
|
||||
func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A { panic(0) }
|
||||
func _() {
|
||||
x := f5(1.2)
|
||||
var _ float64 = x.b
|
||||
var _ float64 = *x.c
|
||||
}
|
||||
|
||||
func f6[A any, B interface{~struct{f []A}}](B) A
|
||||
func f6[A any, B interface{~struct{f []A}}](B) A { panic(0) }
|
||||
func _() {
|
||||
x := f6(struct{f []string}{})
|
||||
var _ string = x
|
||||
|
@ -85,7 +85,7 @@ type NumericAbs[T any] interface {
|
||||
Abs() T
|
||||
}
|
||||
|
||||
func AbsDifference[T NumericAbs[T]](x T)
|
||||
func AbsDifference[T NumericAbs[T]](x T) { panic(0) }
|
||||
|
||||
type OrderedAbs[T any] T
|
||||
|
||||
@ -97,7 +97,7 @@ func OrderedAbsDifference[T any](x T) {
|
||||
|
||||
// same code, reduced to essence
|
||||
|
||||
func g[P interface{ m() P }](x P)
|
||||
func g[P interface{ m() P }](x P) { panic(0) }
|
||||
|
||||
type T4[P any] P
|
||||
|
||||
@ -205,7 +205,7 @@ type I0 interface {
|
||||
E0
|
||||
}
|
||||
|
||||
func f0[T I0]()
|
||||
func f0[T I0]() {}
|
||||
var _ = f0[int]
|
||||
var _ = f0[bool]
|
||||
var _ = f0[string]
|
||||
@ -216,7 +216,7 @@ type I01 interface {
|
||||
E1
|
||||
}
|
||||
|
||||
func f01[T I01]()
|
||||
func f01[T I01]() {}
|
||||
var _ = f01[int]
|
||||
var _ = f01[bool /* ERROR does not satisfy I0 */ ]
|
||||
var _ = f01[string]
|
||||
@ -228,7 +228,7 @@ type I012 interface {
|
||||
E2
|
||||
}
|
||||
|
||||
func f012[T I012]()
|
||||
func f012[T I012]() {}
|
||||
var _ = f012[int /* ERROR does not satisfy I012 */ ]
|
||||
var _ = f012[bool /* ERROR does not satisfy I012 */ ]
|
||||
var _ = f012[string /* ERROR does not satisfy I012 */ ]
|
||||
@ -239,7 +239,7 @@ type I12 interface {
|
||||
E2
|
||||
}
|
||||
|
||||
func f12[T I12]()
|
||||
func f12[T I12]() {}
|
||||
var _ = f12[int /* ERROR does not satisfy I12 */ ]
|
||||
var _ = f12[bool /* ERROR does not satisfy I12 */ ]
|
||||
var _ = f12[string /* ERROR does not satisfy I12 */ ]
|
||||
@ -250,7 +250,7 @@ type I0_ interface {
|
||||
~int
|
||||
}
|
||||
|
||||
func f0_[T I0_]()
|
||||
func f0_[T I0_]() {}
|
||||
var _ = f0_[int]
|
||||
var _ = f0_[bool /* ERROR does not satisfy I0_ */ ]
|
||||
var _ = f0_[string /* ERROR does not satisfy I0_ */ ]
|
||||
|
@ -15,9 +15,9 @@ func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ER
|
||||
|
||||
func identity[T any](x T) T { return x }
|
||||
|
||||
func _[_ any](x int) int
|
||||
func _[T any](T /* ERROR redeclared */ T)()
|
||||
func _[T, T /* ERROR redeclared */ any]()
|
||||
func _[_ any](x int) int { panic(0) }
|
||||
func _[T any](T /* ERROR redeclared */ T)() {}
|
||||
func _[T, T /* ERROR redeclared */ any]() {}
|
||||
|
||||
// Constraints (incl. any) may be parenthesized.
|
||||
func _[_ (any)]() {}
|
||||
@ -77,18 +77,18 @@ func new[T any]() *T {
|
||||
var _ = new /* ERROR cannot use generic function new */
|
||||
var _ *int = new[int]()
|
||||
|
||||
func _[T any](map[T /* ERROR invalid map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable
|
||||
func _[T any](map[T /* ERROR invalid map key type T \(missing comparable constraint\) */]int) {} // w/o constraint we don't know if T is comparable
|
||||
|
||||
func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int
|
||||
func f1[T1 any](struct{T1 /* ERROR cannot be a .* type parameter */ }) int { panic(0) }
|
||||
var _ = f1[int](struct{T1}{})
|
||||
type T1 = int
|
||||
|
||||
func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int
|
||||
func f2[t1 any](struct{t1 /* ERROR cannot be a .* type parameter */ ; x float32}) int { panic(0) }
|
||||
var _ = f2[t1](struct{t1; x float32}{})
|
||||
type t1 = int
|
||||
|
||||
|
||||
func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int
|
||||
func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int { panic(0) }
|
||||
|
||||
var _ = f3[int, rune, bool](1, struct{x rune}{}, nil)
|
||||
|
||||
@ -257,28 +257,28 @@ func _[
|
||||
|
||||
var _ = new() /* ERROR cannot infer T */
|
||||
|
||||
func f4[A, B, C any](A, B) C
|
||||
func f4[A, B, C any](A, B) C { panic(0) }
|
||||
|
||||
var _ = f4(1, 2) /* ERROR cannot infer C */
|
||||
var _ = f4[int, float32, complex128](1, 2)
|
||||
|
||||
func f5[A, B, C any](A, []*B, struct{f []C}) int
|
||||
func f5[A, B, C any](A, []*B, struct{f []C}) int { panic(0) }
|
||||
|
||||
var _ = f5[int, float32, complex128](0, nil, struct{f []complex128}{})
|
||||
var _ = f5(0, nil, struct{f []complex128}{}) // ERROR cannot infer
|
||||
var _ = f5(0, []*float32{new[float32]()}, struct{f []complex128}{})
|
||||
|
||||
func f6[A any](A, []A) int
|
||||
func f6[A any](A, []A) int { panic(0) }
|
||||
|
||||
var _ = f6(0, nil)
|
||||
|
||||
func f6nil[A any](A) int
|
||||
func f6nil[A any](A) int { panic(0) }
|
||||
|
||||
var _ = f6nil(nil) // ERROR cannot infer
|
||||
|
||||
// type inference with variadic functions
|
||||
|
||||
func f7[T any](...T) T
|
||||
func f7[T any](...T) T { panic(0) }
|
||||
|
||||
var _ int = f7() /* ERROR cannot infer T */
|
||||
var _ int = f7(1)
|
||||
@ -291,7 +291,7 @@ var _ = f7(float64(1), 2.3)
|
||||
var _ = f7(1, 2.3 /* ERROR does not match */ )
|
||||
var _ = f7(1.2, 3 /* ERROR does not match */ )
|
||||
|
||||
func f8[A, B any](A, B, ...B) int
|
||||
func f8[A, B any](A, B, ...B) int { panic(0) }
|
||||
|
||||
var _ = f8(1) /* ERROR not enough arguments */
|
||||
var _ = f8(1, 2.3)
|
||||
@ -318,7 +318,7 @@ func (T) m3[P any]() {}
|
||||
|
||||
type S1[P any] struct { f P }
|
||||
|
||||
func f9[P any](x S1[P])
|
||||
func f9[P any](x S1[P]) {}
|
||||
|
||||
func _() {
|
||||
f9[int](S1[int]{42})
|
||||
@ -327,7 +327,7 @@ func _() {
|
||||
|
||||
type S2[A, B, C any] struct{}
|
||||
|
||||
func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool])
|
||||
func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool]) {}
|
||||
|
||||
func _[P any]() {
|
||||
f10[int, float32, string](S2[int, int, string]{}, S2[int, float32, bool]{})
|
||||
@ -338,7 +338,7 @@ func _[P any]() {
|
||||
// corner case for type inference
|
||||
// (was bug: after instanting f11, the type-checker didn't mark f11 as non-generic)
|
||||
|
||||
func f11[T any]()
|
||||
func f11[T any]() {}
|
||||
|
||||
func _() {
|
||||
f11[int]()
|
||||
@ -346,7 +346,7 @@ func _() {
|
||||
|
||||
// the previous example was extracted from
|
||||
|
||||
func f12[T interface{m() T}]()
|
||||
func f12[T interface{m() T}]() {}
|
||||
|
||||
type A[T any] T
|
||||
|
||||
@ -374,15 +374,15 @@ func _[T any] (x T) {
|
||||
|
||||
type R0 struct{}
|
||||
|
||||
func (R0) _[T any](x T)
|
||||
func (R0 /* ERROR invalid receiver */ ) _[R0 any]() // scope of type parameters starts at "func"
|
||||
func (R0) _[T any](x T) {}
|
||||
func (R0 /* ERROR invalid receiver */ ) _[R0 any]() {} // scope of type parameters starts at "func"
|
||||
|
||||
type R1[A, B any] struct{}
|
||||
|
||||
func (_ R1[A, B]) m0(A, B)
|
||||
func (_ R1[A, B]) m1[T any](A, B, T) T
|
||||
func (_ R1[A, B]) m1[T any](A, B, T) T { panic(0) }
|
||||
func (_ R1 /* ERROR not a generic type */ [R1, _]) _()
|
||||
func (_ R1[A, B]) _[A /* ERROR redeclared */ any](B)
|
||||
func (_ R1[A, B]) _[A /* ERROR redeclared */ any](B) {}
|
||||
|
||||
func _() {
|
||||
var r R1[int, string]
|
||||
|
@ -66,7 +66,7 @@ var _ float64 = foo(42, []float64{1.0}, &s)
|
||||
|
||||
// Type inference works in a straight-forward manner even
|
||||
// for variadic functions.
|
||||
func variadic[A, B any](A, B, ...B) int
|
||||
func variadic[A, B any](A, B, ...B) int { panic(0) }
|
||||
|
||||
// var _ = variadic(1) // ERROR not enough arguments
|
||||
var _ = variadic(1, 2.3)
|
||||
@ -118,9 +118,9 @@ func max[T interface{ ~int }](x ...T) T {
|
||||
// Thus even if a type can be inferred successfully, the function
|
||||
// call may not be valid.
|
||||
|
||||
func fboth[T any](chan T)
|
||||
func frecv[T any](<-chan T)
|
||||
func fsend[T any](chan<- T)
|
||||
func fboth[T any](chan T) {}
|
||||
func frecv[T any](<-chan T) {}
|
||||
func fsend[T any](chan<- T) {}
|
||||
|
||||
func _() {
|
||||
var both chan int
|
||||
@ -140,9 +140,9 @@ func _() {
|
||||
fsend(send)
|
||||
}
|
||||
|
||||
func ffboth[T any](func(chan T))
|
||||
func ffrecv[T any](func(<-chan T))
|
||||
func ffsend[T any](func(chan<- T))
|
||||
func ffboth[T any](func(chan T)) {}
|
||||
func ffrecv[T any](func(<-chan T)) {}
|
||||
func ffsend[T any](func(chan<- T)) {}
|
||||
|
||||
func _() {
|
||||
var both func(chan int)
|
||||
@ -169,9 +169,9 @@ func _() {
|
||||
// assignment is permitted, parameter passing is permitted as well,
|
||||
// so type inference should be able to handle these cases well.
|
||||
|
||||
func g1[T any]([]T)
|
||||
func g2[T any]([]T, T)
|
||||
func g3[T any](*T, ...T)
|
||||
func g1[T any]([]T) {}
|
||||
func g2[T any]([]T, T) {}
|
||||
func g3[T any](*T, ...T) {}
|
||||
|
||||
func _() {
|
||||
type intSlize []int
|
||||
@ -195,7 +195,7 @@ func _() {
|
||||
|
||||
// Here's a realistic example.
|
||||
|
||||
func append[T any](s []T, t ...T) []T
|
||||
func append[T any](s []T, t ...T) []T { panic(0) }
|
||||
|
||||
func _() {
|
||||
var f func()
|
||||
@ -208,8 +208,12 @@ func _() {
|
||||
// (that would indicate a slice type). Thus, generic functions cannot
|
||||
// have empty type parameter lists, either. This is a syntax error.
|
||||
|
||||
func h[] /* ERROR empty type parameter list */ ()
|
||||
func h[] /* ERROR empty type parameter list */ () {}
|
||||
|
||||
func _() {
|
||||
h[] /* ERROR operand */ ()
|
||||
}
|
||||
|
||||
// Parameterized functions must have a function body.
|
||||
|
||||
func _ /* ERROR missing function body */ [P any]()
|
||||
|
@ -10,7 +10,7 @@ type Ordered interface {
|
||||
~int|~float64|~string
|
||||
}
|
||||
|
||||
func min[T Ordered](x, y T) T
|
||||
func min[T Ordered](x, y T) T { panic(0) }
|
||||
|
||||
func _() {
|
||||
// min can be called with explicit instantiation.
|
||||
@ -37,7 +37,7 @@ func _() {
|
||||
_ = min("foo", "bar")
|
||||
}
|
||||
|
||||
func mixed[T1, T2, T3 any](T1, T2, T3)
|
||||
func mixed[T1, T2, T3 any](T1, T2, T3) {}
|
||||
|
||||
func _() {
|
||||
// mixed can be called with explicit instantiation.
|
||||
@ -54,7 +54,7 @@ func _() {
|
||||
mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false)
|
||||
}
|
||||
|
||||
func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem)
|
||||
func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) {}
|
||||
|
||||
func _() {
|
||||
// related1 can be called with explicit instantiation.
|
||||
@ -78,7 +78,7 @@ func _() {
|
||||
related1(si, "foo" /* ERROR cannot use "foo" */ )
|
||||
}
|
||||
|
||||
func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice)
|
||||
func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {}
|
||||
|
||||
func _() {
|
||||
// related2 can be called with explicit instantiation.
|
||||
|
@ -216,15 +216,15 @@ type B0 interface {}
|
||||
type B1[_ any] interface{}
|
||||
type B2[_, _ any] interface{}
|
||||
|
||||
func _[T1 B0]()
|
||||
func _[T1 B1[T1]]()
|
||||
func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]()
|
||||
func _[T1 B0]() {}
|
||||
func _[T1 B1[T1]]() {}
|
||||
func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {}
|
||||
|
||||
func _[T1, T2 B0]()
|
||||
func _[T1 B1[T1], T2 B1[T2]]()
|
||||
func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]()
|
||||
func _[T1, T2 B0]() {}
|
||||
func _[T1 B1[T1], T2 B1[T2]]() {}
|
||||
func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {}
|
||||
|
||||
func _[T1 B0, T2 B1[T2]]() // here B1 applies to T2
|
||||
func _[T1 B0, T2 B1[T2]]() {} // here B1 applies to T2
|
||||
|
||||
// When the type argument is left away, the type bound is
|
||||
// instantiated for each type parameter with that type
|
||||
|
@ -50,7 +50,7 @@ func (G15 /* ERROR generic type .* without instantiation */ ) p()
|
||||
|
||||
// crash 16
|
||||
type Foo16[T any] r16 /* ERROR not a type */
|
||||
func r16[T any]() Foo16[Foo16[T]]
|
||||
func r16[T any]() Foo16[Foo16[T]] { panic(0) }
|
||||
|
||||
// crash 17
|
||||
type Y17 interface{ c() }
|
||||
@ -58,7 +58,7 @@ type Z17 interface {
|
||||
c() Y17
|
||||
Y17 /* ERROR duplicate method */
|
||||
}
|
||||
func F17[T Z17](T)
|
||||
func F17[T Z17](T) {}
|
||||
|
||||
// crash 18
|
||||
type o18[T any] []func(_ o18[[]_ /* ERROR cannot use _ */ ])
|
||||
@ -88,5 +88,5 @@ type T26 = interface{ F26[ /* ERROR cannot have type parameters */ Z any]() }
|
||||
func F26[Z any]() T26 { return F26 /* ERROR without instantiation */ /* ERROR missing method */ [] /* ERROR operand */ }
|
||||
|
||||
// crash 27
|
||||
func e27[T any]() interface{ x27 /* ERROR not a type */ }
|
||||
func e27[T any]() interface{ x27 /* ERROR not a type */ } { panic(0) }
|
||||
func x27() { e27( /* ERROR cannot infer T */ ) }
|
@ -6,4 +6,4 @@ package p
|
||||
|
||||
// A constraint must be an interface; it cannot
|
||||
// be a type parameter, for instance.
|
||||
func _[A interface{ ~int }, B A /* ERROR not an interface */ ]()
|
||||
func _[A interface{ ~int }, B A /* ERROR not an interface */ ]() {}
|
||||
|
@ -4,13 +4,13 @@
|
||||
|
||||
package p
|
||||
|
||||
func f1[T1, T2 any](T1, T2, struct{a T1; b T2})
|
||||
func f1[T1, T2 any](T1, T2, struct{a T1; b T2}) {}
|
||||
func _() {
|
||||
f1(42, string("foo"), struct /* ERROR does not match inferred type struct\{a int; b string\} */ {a, b int}{})
|
||||
}
|
||||
|
||||
// simplified test case from issue
|
||||
func f2[T any](_ []T, _ func(T))
|
||||
func f2[T any](_ []T, _ func(T)) {}
|
||||
func _() {
|
||||
f2([]string{}, func /* ERROR does not match inferred type func\(string\) */ (f []byte) {})
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package p
|
||||
type policy[K, V any] interface{}
|
||||
type LRU[K, V any] struct{}
|
||||
|
||||
func NewCache[K, V any](p policy[K, V])
|
||||
func NewCache[K, V any](p policy[K, V]) {}
|
||||
|
||||
func _() {
|
||||
var lru LRU[int, string]
|
||||
|
@ -8,7 +8,7 @@ type A[T any] int
|
||||
|
||||
func (A[T]) m(A[T])
|
||||
|
||||
func f[P interface{m(P)}]()
|
||||
func f[P interface{m(P)}]() {}
|
||||
|
||||
func _() {
|
||||
_ = f[A[int]]
|
||||
|
@ -10,6 +10,6 @@ func _() {
|
||||
|
||||
type S struct {}
|
||||
|
||||
func NewS[T any]() *S
|
||||
func NewS[T any]() *S { panic(0) }
|
||||
|
||||
func (_ *S /* ERROR S is not a generic type */ [T]) M()
|
||||
|
@ -6,8 +6,8 @@ package p
|
||||
|
||||
type T[_ any] int
|
||||
|
||||
func f[_ any]()
|
||||
func g[_, _ any]()
|
||||
func f[_ any]() {}
|
||||
func g[_, _ any]() {}
|
||||
|
||||
func _() {
|
||||
_ = f[T /* ERROR without instantiation */ ]
|
||||
|
@ -79,9 +79,9 @@ type T3[_, _, _ any] struct{}
|
||||
var _ T1[I2 /* ERROR interface contains type constraints */ ]
|
||||
var _ T3[int, I2 /* ERROR interface contains type constraints */ , float32]
|
||||
|
||||
func f1[_ any]() int
|
||||
func f1[_ any]() int { panic(0) }
|
||||
var _ = f1[I2 /* ERROR interface contains type constraints */ ]()
|
||||
func f3[_, _, _ any]() int
|
||||
func f3[_, _, _ any]() int { panic(0) }
|
||||
var _ = f3[int, I2 /* ERROR interface contains type constraints */ , float32]()
|
||||
|
||||
func _(x interface{}) {
|
||||
|
@ -30,8 +30,8 @@ func _[P any]() {
|
||||
)
|
||||
}
|
||||
|
||||
func _[P any, Q interface{ *P | []P | chan P | map[string]P }]()
|
||||
func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]()
|
||||
func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]()
|
||||
func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]()
|
||||
func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]()
|
||||
func _[P any, Q interface{ *P | []P | chan P | map[string]P }]() {}
|
||||
func _[P any, Q interface{ P /* ERROR "cannot embed a type parameter" */ }]() {}
|
||||
func _[P any, Q interface{ ~P /* ERROR "cannot embed a type parameter" */ }]() {}
|
||||
func _[P any, Q interface{ int | P /* ERROR "cannot embed a type parameter" */ }]() {}
|
||||
func _[P any, Q interface{ int | ~P /* ERROR "cannot embed a type parameter" */ }]() {}
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
package p
|
||||
|
||||
func f[_ comparable]()
|
||||
func g[_ interface{interface{comparable; ~int|~string}}]()
|
||||
func f[_ comparable]() {}
|
||||
func g[_ interface{interface{comparable; ~int|~string}}]() {}
|
||||
|
||||
func _[P comparable,
|
||||
Q interface{ comparable; ~int|~string },
|
||||
|
@ -9,9 +9,9 @@
|
||||
package smoketest
|
||||
|
||||
// type parameters for functions
|
||||
func f1[P any]()
|
||||
func f2[P1, P2 any, P3 any]()
|
||||
func f3[P interface{}](x P, y T1[int])
|
||||
func f1[P any]() {}
|
||||
func f2[P1, P2 any, P3 any]() {}
|
||||
func f3[P interface{}](x P, y T1[int]) {}
|
||||
|
||||
// function instantiations
|
||||
var _ = f1[int]
|
||||
|
@ -24,17 +24,17 @@ type (
|
||||
_[T1, T2 any, T3 any] struct{}
|
||||
)
|
||||
|
||||
func _[T any]()
|
||||
func _[T, T any]() // ERROR "T redeclared"
|
||||
func _[T1, T2 any](x T1) T2
|
||||
func _[T any]() {}
|
||||
func _[T, T any]() {} // ERROR "T redeclared"
|
||||
func _[T1, T2 any](x T1) T2 { panic(0) }
|
||||
|
||||
// Type parameters are visible from opening [ to end of function.
|
||||
type C interface{}
|
||||
|
||||
func _[T interface{}]()
|
||||
func _[T C]()
|
||||
func _[T struct{}]() // ERROR "not an interface"
|
||||
func _[T interface{ m() T }]()
|
||||
func _[T interface{}]() {}
|
||||
func _[T C]() {}
|
||||
func _[T struct{}]() {}// ERROR "not an interface"
|
||||
func _[T interface{ m() T }]() {}
|
||||
func _[T1 interface{ m() T2 }, T2 interface{ m() T1 }]() {
|
||||
var _ T1
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ func f1x() {
|
||||
}
|
||||
*/
|
||||
|
||||
func f2[A any, B interface{ type []A }](_ A, _ B)
|
||||
func f2[A any, B interface{ type []A }](_ A, _ B) {}
|
||||
func f2x() {
|
||||
f := f2[byte]
|
||||
f(byte(0), []byte{})
|
||||
@ -105,7 +105,7 @@ func f3x() {
|
||||
}
|
||||
*/
|
||||
|
||||
func f4[A any, B interface{ type []C }, C interface{ type *A }](_ A, _ B, c C)
|
||||
func f4[A any, B interface{ type []C }, C interface{ type *A }](_ A, _ B, c C) {}
|
||||
func f4x() {
|
||||
f := f4[int]
|
||||
var x int
|
||||
@ -118,14 +118,14 @@ func f5[A interface {
|
||||
b B
|
||||
c C
|
||||
}
|
||||
}, B any, C interface{ type *B }](x B) A
|
||||
}, B any, C interface{ type *B }](x B) A { panic(0) }
|
||||
func f5x() {
|
||||
x := f5(1.2)
|
||||
var _ float64 = x.b
|
||||
var _ float64 = *x.c
|
||||
}
|
||||
|
||||
func f6[A any, B interface{ type struct{ f []A } }](B) A
|
||||
func f6[A any, B interface{ type struct{ f []A } }](B) A { panic(0) }
|
||||
func f6x() {
|
||||
x := f6(struct{ f []string }{})
|
||||
var _ string = x
|
||||
|
Loading…
Reference in New Issue
Block a user