From 8892a51745accb2f8d18be1628d9b5bb9ecd78a5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 17 Aug 2022 20:45:08 -0700 Subject: [PATCH] cmd/compile/internal/types2: use go/types/testdata/examples tests Since the examples tests are now identical between the two type checkers, remove the local copy of the examples tests and (for now) use the tests in go/types/testdata/examples instead. Eventually we may decide to move all tests out of the type checker directories and place them in a shared space (e.g. internal/types/testdata). For #54511. Change-Id: Ibd8599d09e781b2219a23114b4b2049757971181 Reviewed-on: https://go-review.googlesource.com/c/go/+/424695 Reviewed-by: Robert Findley Reviewed-by: Robert Griesemer Run-TryBot: Robert Griesemer --- src/cmd/compile/internal/types2/check_test.go | 2 +- .../types2/testdata/examples/constraints.go | 80 ----- .../types2/testdata/examples/functions.go | 219 ------------ .../types2/testdata/examples/inference.go | 116 ------- .../types2/testdata/examples/methods.go | 112 ------- .../types2/testdata/examples/operations.go | 29 -- .../types2/testdata/examples/types.go | 315 ------------------ .../types2/testdata/examples/typesets.go | 59 ---- 8 files changed, 1 insertion(+), 931 deletions(-) delete mode 100644 src/cmd/compile/internal/types2/testdata/examples/constraints.go delete mode 100644 src/cmd/compile/internal/types2/testdata/examples/functions.go delete mode 100644 src/cmd/compile/internal/types2/testdata/examples/inference.go delete mode 100644 src/cmd/compile/internal/types2/testdata/examples/methods.go delete mode 100644 src/cmd/compile/internal/types2/testdata/examples/operations.go delete mode 100644 src/cmd/compile/internal/types2/testdata/examples/types.go delete mode 100644 src/cmd/compile/internal/types2/testdata/examples/typesets.go diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go index 039b0bde00..4f032fbd59 100644 --- a/src/cmd/compile/internal/types2/check_test.go +++ b/src/cmd/compile/internal/types2/check_test.go @@ -299,7 +299,7 @@ func TestManual(t *testing.T) { func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance func TestSpec(t *testing.T) { testDirFiles(t, "../../../../go/types/testdata/spec", 0, false) } -func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 45, false) } +func TestExamples(t *testing.T) { testDirFiles(t, "../../../../go/types/testdata/examples", 45, false) } func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", 0, false) } func testDirFiles(t *testing.T, dir string, colDelta uint, manual bool) { diff --git a/src/cmd/compile/internal/types2/testdata/examples/constraints.go b/src/cmd/compile/internal/types2/testdata/examples/constraints.go deleted file mode 100644 index 5b144893ce..0000000000 --- a/src/cmd/compile/internal/types2/testdata/examples/constraints.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2021 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. - -// This file shows some examples of generic constraint interfaces. - -package p - -type MyInt int - -type ( - // Arbitrary types may be embedded like interfaces. - _ interface{int} - _ interface{~int} - - // Types may be combined into a union. - union interface{int|~string} - - // Union terms must describe disjoint (non-overlapping) type sets. - _ interface{int|int /* ERROR overlapping terms int */ } - _ interface{int|~ /* ERROR overlapping terms ~int */ int } - _ interface{~int|~ /* ERROR overlapping terms ~int */ int } - _ interface{~int|MyInt /* ERROR overlapping terms p.MyInt and ~int */ } - _ interface{int|any} - _ interface{int|~string|union} - _ interface{int|~string|interface{int}} - _ interface{union|int} // interfaces (here: union) are ignored when checking for overlap - _ interface{union|union} // ditto - - // For now we do not permit interfaces with methods in unions. - _ interface{~ /* ERROR invalid use of ~ */ any} - _ interface{int|interface /* ERROR cannot use .* in union */ { m() }} -) - -type ( - // Tilde is not permitted on defined types or interfaces. - foo int - bar any - _ interface{foo} - _ interface{~ /* ERROR invalid use of ~ */ foo } - _ interface{~ /* ERROR invalid use of ~ */ bar } -) - -// Stand-alone type parameters are not permitted as elements or terms in unions. -type ( - _[T interface{ *T } ] struct{} // ok - _[T interface{ int | *T } ] struct{} // ok - _[T interface{ T /* ERROR term cannot be a type parameter */ } ] struct{} - _[T interface{ ~T /* ERROR type in term ~T cannot be a type parameter */ } ] struct{} - _[T interface{ int|T /* ERROR term cannot be a type parameter */ }] struct{} -) - -// Multiple embedded union elements are intersected. The order in which they -// appear in the interface doesn't matter since intersection is a symmetric -// operation. - -type myInt1 int -type myInt2 int - -func _[T interface{ myInt1|myInt2; ~int }]() T { return T(0) } -func _[T interface{ ~int; myInt1|myInt2 }]() T { return T(0) } - -// Here the intersections are empty - there's no type that's in the type set of T. -func _[T interface{ myInt1|myInt2; int }]() T { return T(0 /* ERROR cannot convert */ ) } -func _[T interface{ int; myInt1|myInt2 }]() T { return T(0 /* ERROR cannot convert */ ) } - -// Union elements may be interfaces as long as they don't define -// any methods or embed comparable. - -type ( - Integer interface{ ~int|~int8|~int16|~int32|~int64 } - Unsigned interface{ ~uint|~uint8|~uint16|~uint32|~uint64 } - Floats interface{ ~float32|~float64 } - Complex interface{ ~complex64|~complex128 } - Number interface{ Integer|Unsigned|Floats|Complex } - Ordered interface{ Integer|Unsigned|Floats|~string } - - _ interface{ Number | error /* ERROR cannot use error in union */ } - _ interface{ Ordered | comparable /* ERROR cannot use comparable in union */ } -) diff --git a/src/cmd/compile/internal/types2/testdata/examples/functions.go b/src/cmd/compile/internal/types2/testdata/examples/functions.go deleted file mode 100644 index 244c9dd228..0000000000 --- a/src/cmd/compile/internal/types2/testdata/examples/functions.go +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2019 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. - -// This file shows some examples of type-parameterized functions. - -package p - -// Reverse is a generic function that takes a []T argument and -// reverses that slice in place. -func Reverse[T any](list []T) { - i := 0 - j := len(list)-1 - for i < j { - list[i], list[j] = list[j], list[i] - i++ - j-- - } -} - -func _() { - // Reverse can be called with an explicit type argument. - Reverse[int](nil) - Reverse[string]([]string{"foo", "bar"}) - Reverse[struct{x, y int}]([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}}) - - // Since the type parameter is used for an incoming argument, - // it can be inferred from the provided argument's type. - Reverse([]string{"foo", "bar"}) - Reverse([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}}) - - // But the incoming argument must have a type, even if it's a - // default type. An untyped nil won't work. - // Reverse(nil) // this won't type-check - - // A typed nil will work, though. - Reverse([]int(nil)) -} - -// Certain functions, such as the built-in `new` could be written using -// type parameters. -func new[T any]() *T { - var x T - return &x -} - -// When calling our own `new`, we need to pass the type parameter -// explicitly since there is no (value) argument from which the -// result type could be inferred. We don't try to infer the -// result type from the assignment to keep things simple and -// easy to understand. -var _ = new[int]() -var _ *float64 = new[float64]() // the result type is indeed *float64 - -// A function may have multiple type parameters, of course. -func foo[A, B, C any](a A, b []B, c *C) B { - // do something here - return b[0] -} - -// As before, we can pass type parameters explicitly. -var s = foo[int, string, float64](1, []string{"first"}, new[float64]()) - -// Or we can use type inference. -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 { panic(0) } - -// var _ = variadic(1) // ERROR not enough arguments -var _ = variadic(1, 2.3) -var _ = variadic(1, 2.3, 3.4, 4.5) -var _ = variadic[int, float64](1, 2.3, 3.4, 4) - -// Type inference also works in recursive function calls where -// the inferred type is the type parameter of the caller. -func f1[T any](x T) { - f1(x) -} - -func f2a[T any](x, y T) { - f2a(x, y) -} - -func f2b[T any](x, y T) { - f2b(y, x) -} - -func g2a[P, Q any](x P, y Q) { - g2a(x, y) -} - -func g2b[P, Q any](x P, y Q) { - g2b(y, x) -} - -// Here's an example of a recursive function call with variadic -// arguments and type inference inferring the type parameter of -// the caller (i.e., itself). -func max[T interface{ ~int }](x ...T) T { - var x0 T - if len(x) > 0 { - x0 = x[0] - } - if len(x) > 1 { - x1 := max(x[1:]...) - if x1 > x0 { - return x1 - } - } - return x0 -} - -// When inferring channel types, the channel direction is ignored -// for the purpose of type inference. Once the type has been in- -// fered, the usual parameter passing rules are applied. -// 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 _() { - var both chan int - var recv <-chan int - var send chan<-int - - fboth(both) - fboth(recv /* ERROR cannot use */ ) - fboth(send /* ERROR cannot use */ ) - - frecv(both) - frecv(recv) - frecv(send /* ERROR cannot use */ ) - - fsend(both) - fsend(recv /* ERROR cannot use */) - fsend(send) -} - -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) - var recv func(<-chan int) - var send func(chan<- int) - - ffboth(both) - ffboth(recv /* ERROR cannot use */ ) - ffboth(send /* ERROR cannot use */ ) - - ffrecv(both /* ERROR cannot use */ ) - ffrecv(recv) - ffrecv(send /* ERROR cannot use */ ) - - ffsend(both /* ERROR cannot use */ ) - ffsend(recv /* ERROR cannot use */ ) - ffsend(send) -} - -// When inferring elements of unnamed composite parameter types, -// if the arguments are defined types, use their underlying types. -// Even though the matching types are not exactly structurally the -// same (one is a type literal, the other a named type), because -// 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 _() { - type intSlize []int - g1([]int{}) - g1(intSlize{}) - g2(nil, 0) - - type myString string - var s1 string - g3(nil, "1", myString("2"), "3") - g3(& /* ERROR does not match */ s1, "1", myString("2"), "3") - _ = s1 - - type myStruct struct{x int} - var s2 myStruct - g3(nil, struct{x int}{}, myStruct{}) - g3(&s2, struct{x int}{}, myStruct{}) - g3(nil, myStruct{}, struct{x int}{}) - g3(&s2, myStruct{}, struct{x int}{}) -} - -// Here's a realistic example. - -func append[T any](s []T, t ...T) []T { panic(0) } - -func _() { - var f func() - type Funcs []func() - var funcs Funcs - _ = append(funcs, f) -} - -// Generic type declarations cannot have empty type parameter lists -// (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 cannot index */ [] /* ERROR operand */ () -} - -// Parameterized functions must have a function body. - -func _ /* ERROR missing function body */ [P any]() diff --git a/src/cmd/compile/internal/types2/testdata/examples/inference.go b/src/cmd/compile/internal/types2/testdata/examples/inference.go deleted file mode 100644 index 23a3d81f3d..0000000000 --- a/src/cmd/compile/internal/types2/testdata/examples/inference.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2021 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. - -// This file shows some examples of type inference. - -package p - -type Ordered interface { - ~int | ~float64 | ~string -} - -func min[T Ordered](x, y T) T { panic(0) } - -func _() { - // min can be called with explicit instantiation. - _ = min[int](1, 2) - - // Alternatively, the type argument can be inferred from - // one of the arguments. Untyped arguments will be considered - // last. - var x int - _ = min(x, x) - _ = min(x, 1) - _ = min(x, 1.0) - _ = min(1, 2) - _ = min(1, 2.3 /* ERROR default type float64 .* does not match */) - - var y float64 - _ = min(1, y) - _ = min(1.2, y) - _ = min(1.2, 3.4) - _ = min(1.2, 3 /* ERROR default type int .* does not match */) - - var s string - _ = min(s, "foo") - _ = min("foo", "bar") -} - -func mixed[T1, T2, T3 any](T1, T2, T3) {} - -func _() { - // mixed can be called with explicit instantiation. - mixed[int, string, bool](0, "", false) - - // Alternatively, partial type arguments may be provided - // (from left to right), and the other may be inferred. - mixed[int, string](0, "", false) - mixed[int](0, "", false) - mixed(0, "", false) - - // Provided type arguments always take precedence over - // inferred types. - mixed[int, string](1.1 /* ERROR cannot use 1.1 */, "", false) -} - -func related1[Slice interface{ ~[]Elem }, Elem any](s Slice, e Elem) {} - -func _() { - // related1 can be called with explicit instantiation. - var si []int - related1[[]int, int](si, 0) - - // Alternatively, the 2nd type argument can be inferred - // from the first one through constraint type inference. - var ss []string - _ = related1[[]string] - related1[[]string](ss, "foo") - - // A type argument inferred from another explicitly provided - // type argument overrides whatever value argument type is given. - related1[[]string](ss, 0 /* ERROR cannot use 0 */) - - // A type argument may be inferred from a value argument - // and then help infer another type argument via constraint - // type inference. - related1(si, 0) - related1(si, "foo" /* ERROR cannot use "foo" */) -} - -func related2[Elem any, Slice interface{ []Elem }](e Elem, s Slice) {} - -func _() { - // related2 can be called with explicit instantiation. - var si []int - related2[int, []int](0, si) - - // Alternatively, the 2nd type argument can be inferred - // from the first one through constraint type inference. - var ss []string - _ = related2[string] - related2[string]("foo", ss) - - // A type argument may be inferred from a value argument - // and then help infer another type argument via constraint - // type inference. Untyped arguments are always considered - // last. - related2(1.2, []float64{}) - related2(1.0, []int{}) - related2 /* ERROR does not implement */ (float64(1.0), []int{}) // TODO(gri) fix error position -} - -type List[P any] []P - -func related3[Elem any, Slice []Elem | List[Elem]]() Slice { return nil } - -func _() { - // related3 can be instantiated explicitly - related3[int, []int]() - related3[byte, List[byte]]() - - // The 2nd type argument cannot be inferred from the first - // one because there's two possible choices: []Elem and - // List[Elem]. - related3 /* ERROR cannot infer Slice */ [int]() -} diff --git a/src/cmd/compile/internal/types2/testdata/examples/methods.go b/src/cmd/compile/internal/types2/testdata/examples/methods.go deleted file mode 100644 index a46f789d60..0000000000 --- a/src/cmd/compile/internal/types2/testdata/examples/methods.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2019 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. - -// This file shows some examples of methods on type-parameterized types. - -package p - -// Parameterized types may have methods. -type T1[A any] struct{ a A } - -// When declaring a method for a parameterized type, the "instantiated" -// receiver type acts as an implicit declaration of the type parameters -// for the receiver type. In the example below, method m1 on type T1 has -// the receiver type T1[A] which declares the type parameter A for use -// with this method. That is, within the method m1, A stands for the -// actual type argument provided to an instantiated T1. -func (t T1[A]) m1() A { return t.a } - -// For instance, if T1 is instantiated with the type int, the type -// parameter A in m1 assumes that type (int) as well and we can write -// code like this: -var x T1[int] -var _ int = x.m1() - -// Because the type parameter provided to a parameterized receiver type -// is declared through that receiver declaration, it must be an identifier. -// It cannot possibly be some other type because the receiver type is not -// instantiated with concrete types, it is standing for the parameterized -// receiver type. -func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {} - -// Note that using what looks like a predeclared identifier, say int, -// as type parameter in this situation is deceptive and considered bad -// style. In m3 below, int is the name of the local receiver type parameter -// and it shadows the predeclared identifier int which then cannot be used -// anymore as expected. -// This is no different from locally re-declaring a predeclared identifier -// and usually should be avoided. There are some notable exceptions; e.g., -// sometimes it makes sense to use the identifier "copy" which happens to -// also be the name of a predeclared built-in function. -func (t T1[int]) m3() { var _ int = 42 /* ERROR cannot use 42 .* as int */ } - -// The names of the type parameters used in a parameterized receiver -// type don't have to match the type parameter names in the declaration -// of the type used for the receiver. In our example, even though T1 is -// declared with type parameter named A, methods using that receiver type -// are free to use their own name for that type parameter. That is, the -// name of type parameters is always local to the declaration where they -// are introduced. In our example we can write a method m2 and use the -// name X instead of A for the type parameter w/o any difference. -func (t T1[X]) m4() X { return t.a } - -// If the receiver type is parameterized, type parameters must always be -// provided: this simply follows from the general rule that a parameterized -// type must be instantiated before it can be used. A method receiver -// declaration using a parameterized receiver type is no exception. It is -// simply that such receiver type expressions perform two tasks simultaneously: -// they declare the (local) type parameters and then use them to instantiate -// the receiver type. Forgetting to provide a type parameter leads to an error. -func (t T1 /* ERROR generic type .* without instantiation */ ) m5() {} - -// However, sometimes we don't need the type parameter, and thus it is -// inconvenient to have to choose a name. Since the receiver type expression -// serves as a declaration for its type parameters, we are free to choose the -// blank identifier: -func (t T1[_]) m6() {} - -// Naturally, these rules apply to any number of type parameters on the receiver -// type. Here are some more complex examples. -type T2[A, B, C any] struct { - a A - b B - c C -} - -// Naming of the type parameters is local and has no semantic impact: -func (t T2[A, B, C]) m1() (A, B, C) { return t.a, t.b, t.c } -func (t T2[C, B, A]) m2() (C, B, A) { return t.a, t.b, t.c } -func (t T2[X, Y, Z]) m3() (X, Y, Z) { return t.a, t.b, t.c } - -// Type parameters may be left blank if they are not needed: -func (t T2[A, _, C]) m4() (A, C) { return t.a, t.c } -func (t T2[_, _, X]) m5() X { return t.c } -func (t T2[_, _, _]) m6() {} - -// As usual, blank names may be used for any object which we don't care about -// using later. For instance, we may write an unnamed method with a receiver -// that cannot be accessed: -func (_ T2[_, _, _]) _() int { return 42 } - -// Because a receiver parameter list is simply a parameter list, we can -// leave the receiver argument away for receiver types. -type T0 struct{} -func (T0) _() {} -func (T1[A]) _() {} - -// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). -// // A generic receiver type may constrain its type parameter such -// // that it must be a pointer type. Such receiver types are not -// // permitted. -// type T3a[P interface{ ~int | ~string | ~float64 }] P -// -// func (T3a[_]) m() {} // this is ok -// -// type T3b[P interface{ ~unsafe.Pointer }] P -// -// func (T3b /* ERROR invalid receiver */ [_]) m() {} -// -// type T3c[P interface{ *int | *string }] P -// -// func (T3c /* ERROR invalid receiver */ [_]) m() {} diff --git a/src/cmd/compile/internal/types2/testdata/examples/operations.go b/src/cmd/compile/internal/types2/testdata/examples/operations.go deleted file mode 100644 index 18e4d6080c..0000000000 --- a/src/cmd/compile/internal/types2/testdata/examples/operations.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2021 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 p - -// indirection - -func _[P any](p P) { - _ = *p // ERROR cannot indirect p -} - -func _[P interface{ int }](p P) { - _ = *p // ERROR cannot indirect p -} - -func _[P interface{ *int }](p P) { - _ = *p -} - -func _[P interface{ *int | *string }](p P) { - _ = *p // ERROR must have identical base types -} - -type intPtr *int - -func _[P interface{ *int | intPtr } ](p P) { - var _ int = *p -} diff --git a/src/cmd/compile/internal/types2/testdata/examples/types.go b/src/cmd/compile/internal/types2/testdata/examples/types.go deleted file mode 100644 index 052d168fc6..0000000000 --- a/src/cmd/compile/internal/types2/testdata/examples/types.go +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright 2019 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. - -// This file shows some examples of generic types. - -package p - -// List is just what it says - a slice of E elements. -type List[E any] []E - -// A generic (parameterized) type must always be instantiated -// before it can be used to designate the type of a variable -// (including a struct field, or function parameter); though -// for the latter cases, the provided type may be another type -// parameter. So: -var _ List[byte] = []byte{} - -// A generic binary tree might be declared as follows. -type Tree[E any] struct { - left, right *Tree[E] - payload E -} - -// A simple instantiation of Tree: -var root1 Tree[int] - -// The actual type parameter provided may be a generic type itself: -var root2 Tree[List[int]] - -// A couple of more complex examples. -// We don't need extra parentheses around the element type of the slices on -// the right (unlike when we use ()'s rather than []'s for type parameters). -var _ List[List[int]] = []List[int]{} -var _ List[List[List[Tree[int]]]] = []List[List[Tree[int]]]{} - -// Type parameters act like type aliases when used in generic types -// in the sense that we can "emulate" a specific type instantiation -// with type aliases. -type T1[P any] struct { - f P -} - -type T2[P any] struct { - f struct { - g P - } -} - -var x1 T1[struct{ g int }] -var x2 T2[int] - -func _() { - // This assignment is invalid because the types of x1, x2 are T1(...) - // and T2(...) respectively, which are two different defined types. - x1 = x2 // ERROR assignment - - // This assignment is valid because the types of x1.f and x2.f are - // both struct { g int }; the type parameters act like type aliases - // and their actual names don't come into play here. - x1.f = x2.f -} - -// We can verify this behavior using type aliases instead: -type T1a struct { - f A1 -} -type A1 = struct { g int } - -type T2a struct { - f struct { - g A2 - } -} -type A2 = int - -var x1a T1a -var x2a T2a - -func _() { - x1a = x2a // ERROR assignment - x1a.f = x2a.f -} - -// Another interesting corner case are generic types that don't use -// their type arguments. For instance: -type T[P any] struct{} - -var xint T[int] -var xbool T[bool] - -// Are these two variables of the same type? After all, their underlying -// types are identical. We consider them to be different because each type -// instantiation creates a new named type, in this case T and T -// even if their underlying types are identical. This is sensible because -// we might still have methods that have different signatures or behave -// differently depending on the type arguments, and thus we can't possibly -// consider such types identical. Consequently: -func _() { - xint = xbool // ERROR assignment -} - -// Generic types cannot be used without instantiation. -var _ T // ERROR cannot use generic type T -var _ = T /* ERROR cannot use generic type T */ (0) - -// In type context, generic (parameterized) types cannot be parenthesized before -// being instantiated. See also NOTES entry from 12/4/2019. -var _ (T /* ERROR cannot use generic type T */ )[ /* ERROR unexpected \[|expected ';' */ int] - -// All types may be parameterized, including interfaces. -type I1[T any] interface{ - m1(T) -} - -// There is no such thing as a variadic generic type. -type _[T ... /* ERROR invalid use of ... */ any] struct{} - -// Generic interfaces may be embedded as one would expect. -type I2 interface { - I1(int) // method! - I1[string] // embedded I1 -} - -func _() { - var x I2 - x.I1(0) - x.m1("foo") -} - -type I0 interface { - m0() -} - -type I3 interface { - I0 - I1[bool] - m(string) -} - -func _() { - var x I3 - x.m0() - x.m1(true) - x.m("foo") -} - -type _ struct { - ( /* ERROR cannot parenthesize */ int8) - ( /* ERROR cannot parenthesize */ *int16) - *( /* ERROR cannot parenthesize */ int32) - List[int] - - int8 /* ERROR int8 redeclared */ - * /* ERROR int16 redeclared */ int16 - List /* ERROR List redeclared */ [int] -} - -// Issue #45639: We don't allow this anymore. Keep this code -// in case we decide to revisit this decision. -// -// It's possible to declare local types whose underlying types -// are type parameters. As with ordinary type definitions, the -// types underlying properties are "inherited" but the methods -// are not. -// func _[T interface{ m(); ~int }]() { -// type L T -// var x L -// -// // m is not defined on L (it is not "inherited" from -// // its underlying type). -// x.m /* ERROR x.m undefined */ () -// -// // But the properties of T, such that as that it supports -// // the operations of the types given by its type bound, -// // are also the properties of L. -// x++ -// _ = x - x -// -// // On the other hand, if we define a local alias for T, -// // that alias stands for T as expected. -// type A = T -// var y A -// y.m() -// _ = y < 0 -// } - -// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639). -// // It is not permitted to declare a local type whose underlying -// // type is a type parameter not declared by that type declaration. -// func _[T any]() { -// type _ T // ERROR cannot use function type parameter T as RHS in type declaration -// type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration -// } - -// As a special case, an explicit type argument may be omitted -// from a type parameter bound if the type bound expects exactly -// one type argument. In that case, the type argument is the -// respective type parameter to which the type bound applies. -// Note: We may not permit this syntactic sugar at first. -// Note: This is now disabled. All examples below are adjusted. -type Adder[T any] interface { - Add(T) T -} - -// We don't need to explicitly instantiate the Adder bound -// if we have exactly one type parameter. -func Sum[T Adder[T]](list []T) T { - var sum T - for _, x := range list { - sum = sum.Add(x) - } - return sum -} - -// Valid and invalid variations. -type B0 any -type B1[_ any] any -type B2[_, _ any] any - -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 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 -// parameter. -// Note: We may not permit this syntactic sugar at first. -func _[A Adder[A], B Adder[B], C Adder[A]]() { - var a A // A's type bound is Adder[A] - a = a.Add(a) - var b B // B's type bound is Adder[B] - b = b.Add(b) - var c C // C's type bound is Adder[A] - a = c.Add(a) -} - -// The type of variables (incl. parameters and return values) cannot -// be an interface with type constraints or be/embed comparable. -type I interface { - ~int -} - -var ( - _ interface /* ERROR contains type constraints */ {~int} - _ I /* ERROR contains type constraints */ -) - -func _(I /* ERROR contains type constraints */ ) -func _(x, y, z I /* ERROR contains type constraints */ ) -func _() I /* ERROR contains type constraints */ - -func _() { - var _ I /* ERROR contains type constraints */ -} - -type C interface { - comparable -} - -var _ comparable /* ERROR comparable */ -var _ C /* ERROR comparable */ - -func _(_ comparable /* ERROR comparable */ , _ C /* ERROR comparable */ ) - -func _() { - var _ comparable /* ERROR comparable */ - var _ C /* ERROR comparable */ -} - -// Type parameters are never const types, i.e., it's -// not possible to declare a constant of type parameter type. -// (If a type set contains just a single const type, we could -// allow it, but such type sets don't make much sense in the -// first place.) -func _[T interface{~int|~float64}]() { - // not valid - const _ = T /* ERROR not constant */ (0) - const _ T /* ERROR invalid constant type T */ = 1 - - // valid - var _ = T(0) - var _ T = 1 - _ = T(0) -} - -// It is possible to create composite literals of type parameter -// type as long as it's possible to create a composite literal -// of the core type of the type parameter's constraint. -func _[P interface{ ~[]int }]() P { - return P{} - return P{1, 2, 3} -} - -func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P { - x := P{} - return P{{}} - return P{E{}} - return P{E{"foo": x}} - return P{{"foo": x}, {}} -} - -// This is a degenerate case with a singleton type set, but we can create -// composite literals even if the core type is a defined type. -type MyInts []int - -func _[P MyInts]() P { - return P{} -} diff --git a/src/cmd/compile/internal/types2/testdata/examples/typesets.go b/src/cmd/compile/internal/types2/testdata/examples/typesets.go deleted file mode 100644 index a50beb9745..0000000000 --- a/src/cmd/compile/internal/types2/testdata/examples/typesets.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2021 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. - -// This file shows some examples of constraint literals with elided interfaces. -// These examples are permitted if proposal issue #48424 is accepted. - -package p - -// Constraint type sets of the form T, ~T, or A|B may omit the interface. -type ( - _[T int] struct{} - _[T ~int] struct{} - _[T int | string] struct{} - _[T ~int | ~string] struct{} -) - -func min[T int | string](x, y T) T { - if x < y { - return x - } - return y -} - -func lookup[M ~map[K]V, K comparable, V any](m M, k K) V { - return m[k] -} - -func deref[P ~*E, E any](p P) E { - return *p -} - -func _() int { - p := new(int) - return deref(p) -} - -func addrOfCopy[V any, P *V](v V) P { - return &v -} - -func _() *int { - return addrOfCopy(0) -} - -// A type parameter may not be embedded in an interface; -// so it can also not be used as a constraint. -func _[A any, B A /* ERROR cannot use a type parameter as constraint */]() {} -func _[A any, B, C A /* ERROR cannot use a type parameter as constraint */]() {} - -// Error messages refer to the type constraint as it appears in the source. -// (No implicit interface should be exposed.) -func _[T string](x T) T { - return x /* ERROR constrained by string */ * x -} - -func _[T int | string](x T) T { - return x /* ERROR constrained by int|string */ * x -} -- 2.50.0