Skip to content

Commit

Permalink
[dev.go2go] go/types: adjust all tests to use latest syntax
Browse files Browse the repository at this point in the history
- use square brackets for type parameters
- otherwise, use same syntax as for ordinary parameters:
  all type parameters must have a constraint, can be "any"
- remove (rename) all *B.go2 tests in favor of adjusted *.go2 tests
- remove tests related to pointer notation for type parameters
  (we are going to use constraint type inference instead)
- adjust type string computation accordingly
- minor related adjustments

This change can be reverted if we don't like it.

Change-Id: Ie1034e0996df8f5ca6fbdf9ecaa3c93fcfd7106d
Reviewed-on: https://go-review.googlesource.com/c/go/+/249741
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
  • Loading branch information
griesemer committed Aug 26, 2020
1 parent 7d90fb0 commit 1964d56
Show file tree
Hide file tree
Showing 59 changed files with 634 additions and 3,076 deletions.
52 changes: 26 additions & 26 deletions src/go/types/api_test.go
Expand Up @@ -277,20 +277,20 @@ func TestTypesInfo(t *testing.T) {
{`package x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},

// parameterized functions
{`package p0; func f(type T)(T); var _ = f(int)`, `f`, `func(type T₁)(T₁)`},
{`package p1; func f(type T)(T); var _ = f(int)`, `f(int)`, `func(int)`},
{`package p2; func f(type T)(T); var _ = f(42)`, `f`, `func(type T₁)(T₁)`},
{`package p2; func f(type T)(T); var _ = f(42)`, `f(42)`, `()`},
{`package p0; func f[T any](T); var _ = f(int)`, `f`, `func[T₁ any](T₁)`},
{`package p1; func f[T any](T); var _ = f(int)`, `f(int)`, `func(int)`},
{`package p2; func f[T any](T); var _ = f(42)`, `f`, `func[T₁ any](T₁)`},
{`package p2; func f[T any](T); var _ = f(42)`, `f(42)`, `()`},

// type parameters
{`package t0; type t(type) int; var _ t`, `t`, `t0.t`},
{`package t1; type t(type P) int; var _ t(int)`, `t`, `t1.t(type P₁)`},
{`package t2; type t(type P interface{}) int; var _ t(int)`, `t`, `t2.t(type P₁)`},
{`package t3; type t(type P, Q interface{}) int; var _ t(int, int)`, `t`, `t3.t(type P₁, Q₂)`},
{`package t4; type t(type P, Q interface{ m() }) int; var _ t(int, int)`, `t`, `t4.t(type P₁, Q₂ interface{m()})`},
{`package t0; type t[any] int; var _ t`, `t`, `t0.t`},
{`package t1; type t[P any] int; var _ t[int]`, `t`, `t1.t[P₁ any]`},
{`package t2; type t[P interface{}] int; var _ t[int]`, `t`, `t2.t[P₁ interface{}]`},
{`package t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `t3.t[P₁, Q₂ interface{}]`},
{`package t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `t4.t[P₁, Q₂ interface{m()}]`},

// instantiated types must be sanitized
{`package g0; type t(type P) int; var x struct{ f t(int) }; var _ = x.f`, `x.f`, `g0.t(int)`},
{`package g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `g0.t[int]`},
}

for _, test := range tests {
Expand Down Expand Up @@ -324,17 +324,17 @@ func TestInferredInfo(t *testing.T) {
targs []string
sig string
}{
{`package p0; func f(type T)(T); func _() { f(42) }`,
{`package p0; func f[T any](T); func _() { f(42) }`,
`f`,
[]string{`int`},
`func(int)`,
},
{`package p1; func f(type T)(T) T; func _() { f('@') }`,
{`package p1; func f[T any](T) T; func _() { f('@') }`,
`f`,
[]string{`rune`},
`func(rune) rune`,
},
{`package p2; func f(type T)(...T) T; func _() { f(0i) }`,
{`package p2; func f[T any](...T) T; func _() { f(0i) }`,
`f`,
[]string{`complex128`},
`func(...complex128) complex128`,
Expand All @@ -351,17 +351,17 @@ func TestInferredInfo(t *testing.T) {
},

// we don't know how to translate these but we can type-check them
{`package q0; type T struct{}; func (T) m(type P)(P); func _(x T) { x.m(42) }`,
{`package q0; type T struct{}; func (T) m[P any](P); func _(x T) { x.m(42) }`,
`x.m`,
[]string{`int`},
`func(int)`,
},
{`package q1; type T struct{}; func (T) m(type P)(P) P; func _(x T) { x.m(42) }`,
{`package q1; type T struct{}; func (T) m[P any](P) P; func _(x T) { x.m(42) }`,
`x.m`,
[]string{`int`},
`func(int) int`,
},
{`package q2; type T struct{}; func (T) m(type P)(...P) P; func _(x T) { x.m(42) }`,
{`package q2; type T struct{}; func (T) m[P any](...P) P; func _(x T) { x.m(42) }`,
`x.m`,
[]string{`int`},
`func(...int) int`,
Expand All @@ -377,12 +377,12 @@ func TestInferredInfo(t *testing.T) {
`func(float64, *byte, ...[]byte)`,
},

{`package r0; type T(type P) struct{}; func (_ T(P)) m(type Q)(Q); func _(type P)(x T(P)) { x.m(42) }`,
{`package r0; type T[P any] struct{}; func (_ T[P]) m[type Q](Q); func _[P any](x T[P]) { x.m(42) }`,
`x.m`,
[]string{`int`},
`func(int)`,
},
{`package r1; type T interface{ m(type P)(P) }; func _(x T) { x.m(4.2) }`,
{`package r1; type T interface{ m(type P any)(P) }; func _(x T) { x.m(4.2) }`,
`x.m`,
[]string{`float64`},
`func(float64)`,
Expand Down Expand Up @@ -445,10 +445,10 @@ func TestDefsInfo(t *testing.T) {

// generic types must be sanitized
// (need to use sufficiently nested types to provoke unexpanded types)
{`package g0; type t(type P) P; const x = (t(int))(42)`, `x`, `const g0.x g0.t(int)`},
{`package g1; type t(type P) P; var x = (t(int))(42)`, `x`, `var g1.x g1.t(int)`},
{`package g2; type t(type P) P; type x struct{ f t(int) }`, `x`, `type g2.x struct{f g2.t(int)}`},
{`package g3; type t(type P) P; func f(x struct{ f t(string) }); var g = f`, `g`, `var g3.g func(x struct{f g3.t(string)})`},
{`package g0; type t[P any] P; const x = t[int](42)`, `x`, `const g0.x g0.t[int]`},
{`package g1; type t[P any] P; var x = t[int](42)`, `x`, `var g1.x g1.t[int]`},
{`package g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type g2.x struct{f g2.t[int]}`},
{`package g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var g3.g func(x struct{f g3.t[string]})`},
}

for _, test := range tests {
Expand Down Expand Up @@ -490,10 +490,10 @@ func TestUsesInfo(t *testing.T) {

// generic types must be sanitized
// (need to use sufficiently nested types to provoke unexpanded types)
{`package g0; func _() { _ = x }; type t(type P) P; const x = (t(int))(42)`, `x`, `const g0.x g0.t(int)`},
{`package g1; func _() { _ = x }; type t(type P) P; var x = (t(int))(42)`, `x`, `var g1.x g1.t(int)`},
{`package g2; func _() { type _ x }; type t(type P) P; type x struct{ f t(int) }`, `x`, `type g2.x struct{f g2.t(int)}`},
{`package g3; func _() { _ = f }; type t(type P) P; func f(x struct{ f t(string) })`, `f`, `func g3.f(x struct{f g3.t(string)})`},
{`package g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const g0.x g0.t[int]`},
{`package g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var g1.x g1.t[int]`},
{`package g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type g2.x struct{f g2.t[int]}`},
{`package g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func g3.f(x struct{f g3.t[string]})`},
}

for _, test := range tests {
Expand Down
2 changes: 1 addition & 1 deletion src/go/types/check_test.go
Expand Up @@ -71,7 +71,7 @@ func parseFiles(t *testing.T, filenames []string) ([]*ast.File, []error) {
var files []*ast.File
var errlist []error
for _, filename := range filenames {
file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors|parser.UnifiedParamLists)
if file == nil {
t.Fatalf("%s: %s", filename, err)
}
Expand Down
54 changes: 27 additions & 27 deletions src/go/types/examples/functions.go2
Expand Up @@ -8,7 +8,7 @@ package p

// Reverse is a generic function that takes a []T argument and
// reverses that slice in place.
func Reverse (type T) (list []T) {
func Reverse[T any](list []T) {
i := 0
j := len(list)-1
for i < j {
Expand All @@ -20,9 +20,9 @@ func Reverse (type T) (list []T) {

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}})
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.
Expand All @@ -34,12 +34,12 @@ func _() {
// Reverse(nil) // this won't type-check

// A typed nil will work, though.
Reverse([]int(nil))
Reverse[[]int(nil)]
}

// Certain functions, such as the built-in `new` could be written using
// type parameters.
func new (type T) () *T {
func new[T any]() *T {
var x T
return &x
}
Expand All @@ -49,56 +49,56 @@ func new (type T) () *T {
// 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 _ = new[int]()
var _ *float64 = new(float64)() // the result type is indeed *float64

// A function may have multiple type parameters, of course.
func foo (type A, B, C) (a A, b []B, c *C) B {
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)())
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(type A, B)(A, B, ...B) int
func variadic[A, B any](A, B, ...B) int

// 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)
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(type T)(x T) {
func f1[T any](x T) {
f1(x)
}

func f2a(type T)(x, y T) {
func f2a[T any](x, y T) {
f2a(x, y)
}

func f2b(type T)(x, y T) {
func f2b[T any](x, y T) {
f2b(y, x)
}

func g2a(type P, Q)(x P, y Q) {
func g2a[P, Q any](x P, y Q) {
g2a(x, y)
}

func g2b(type P, Q)(x P, y Q) {
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(type T interface{ type int })(x ...T) T {
func max[T interface{ type int }](x ...T) T {
var x0 T
if len(x) > 0 {
x0 = x[0]
Expand All @@ -118,9 +118,9 @@ func max(type T interface{ type int })(x ...T) T {
// Thus even if a type can be inferred successfully, the function
// call may not be valid.

func fboth(type T)(chan T)
func frecv(type T)(<-chan T)
func fsend(type T)(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
Expand All @@ -140,9 +140,9 @@ func _() {
fsend(send)
}

func ffboth(type T)(func(chan T))
func ffrecv(type T)(func(<-chan T))
func ffsend(type T)(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)
Expand All @@ -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(type T)([]T)
func g2(type T)([]T, T)
func g3(type T)(*T, ...T)
func g1[T any]([]T)
func g2[T any]([]T, T)
func g3[T any](*T, ...T)

func _() {
type intSlize []int
Expand All @@ -194,7 +194,7 @@ func _() {

// Here's a realistic example.

func append(type T)(s []T, t ...T) []T
func append[T any](s []T, t ...T) []T

func _() {
var f func()
Expand Down

0 comments on commit 1964d56

Please sign in to comment.