1// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// This file shows some examples of type-parameterized functions.
6
7package p
8
9// Reverse is a generic function that takes a []T argument and
10// reverses that slice in place.
11func Reverse[T any](list []T) {
12	i := 0
13	j := len(list)-1
14	for i < j {
15		list[i], list[j] = list[j], list[i]
16		i++
17		j--
18	}
19}
20
21func _() {
22	// Reverse can be called with an explicit type argument.
23	Reverse[int](nil)
24	Reverse[string]([]string{"foo", "bar"})
25	Reverse[struct{x, y int}]([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
26
27	// Since the type parameter is used for an incoming argument,
28	// it can be inferred from the provided argument's type.
29	Reverse([]string{"foo", "bar"})
30	Reverse([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
31
32	// But the incoming argument must have a type, even if it's a
33	// default type. An untyped nil won't work.
34	// Reverse(nil) // this won't type-check
35
36	// A typed nil will work, though.
37	Reverse([]int(nil))
38}
39
40// Certain functions, such as the built-in `new` could be written using
41// type parameters.
42func new[T any]() *T {
43	var x T
44	return &x
45}
46
47// When calling our own `new`, we need to pass the type parameter
48// explicitly since there is no (value) argument from which the
49// result type could be inferred. We don't try to infer the
50// result type from the assignment to keep things simple and
51// easy to understand.
52var _ = new[int]()
53var _ *float64 = new[float64]() // the result type is indeed *float64
54
55// A function may have multiple type parameters, of course.
56func foo[A, B, C any](a A, b []B, c *C) B {
57	// do something here
58	return b[0]
59}
60
61// As before, we can pass type parameters explicitly.
62var s = foo[int, string, float64](1, []string{"first"}, new[float64]())
63
64// Or we can use type inference.
65var _ float64 = foo(42, []float64{1.0}, &s)
66
67// Type inference works in a straight-forward manner even
68// for variadic functions.
69func variadic[A, B any](A, B, ...B) int { panic(0) }
70
71// var _ = variadic(1) // ERROR not enough arguments
72var _ = variadic(1, 2.3)
73var _ = variadic(1, 2.3, 3.4, 4.5)
74var _ = variadic[int, float64](1, 2.3, 3.4, 4)
75
76// Type inference also works in recursive function calls where
77// the inferred type is the type parameter of the caller.
78func f1[T any](x T) {
79	f1(x)
80}
81
82func f2a[T any](x, y T) {
83	f2a(x, y)
84}
85
86func f2b[T any](x, y T) {
87	f2b(y, x)
88}
89
90func g2a[P, Q any](x P, y Q) {
91	g2a(x, y)
92}
93
94func g2b[P, Q any](x P, y Q) {
95	g2b(y, x)
96}
97
98// Here's an example of a recursive function call with variadic
99// arguments and type inference inferring the type parameter of
100// the caller (i.e., itself).
101func max[T interface{ ~int }](x ...T) T {
102	var x0 T
103	if len(x) > 0 {
104		x0 = x[0]
105	}
106	if len(x) > 1 {
107		x1 := max(x[1:]...)
108		if x1 > x0 {
109			return x1
110		}
111	}
112	return x0
113}
114
115// When inferring channel types, the channel direction is ignored
116// for the purpose of type inference. Once the type has been in-
117// fered, the usual parameter passing rules are applied.
118// Thus even if a type can be inferred successfully, the function
119// call may not be valid.
120
121func fboth[T any](chan T) {}
122func frecv[T any](<-chan T) {}
123func fsend[T any](chan<- T) {}
124
125func _() {
126	var both chan int
127	var recv <-chan int
128	var send chan<-int
129
130	fboth(both)
131	fboth(recv /* ERROR cannot use */ )
132	fboth(send /* ERROR cannot use */ )
133
134	frecv(both)
135	frecv(recv)
136	frecv(send /* ERROR cannot use */ )
137
138	fsend(both)
139	fsend(recv /* ERROR cannot use */)
140	fsend(send)
141}
142
143func ffboth[T any](func(chan T)) {}
144func ffrecv[T any](func(<-chan T)) {}
145func ffsend[T any](func(chan<- T)) {}
146
147func _() {
148	var both func(chan int)
149	var recv func(<-chan int)
150	var send func(chan<- int)
151
152	ffboth(both)
153	ffboth(recv /* ERROR cannot use */ )
154	ffboth(send /* ERROR cannot use */ )
155
156	ffrecv(both /* ERROR cannot use */ )
157	ffrecv(recv)
158	ffrecv(send /* ERROR cannot use */ )
159
160	ffsend(both /* ERROR cannot use */ )
161	ffsend(recv /* ERROR cannot use */ )
162	ffsend(send)
163}
164
165// When inferring elements of unnamed composite parameter types,
166// if the arguments are defined types, use their underlying types.
167// Even though the matching types are not exactly structurally the
168// same (one is a type literal, the other a named type), because
169// assignment is permitted, parameter passing is permitted as well,
170// so type inference should be able to handle these cases well.
171
172func g1[T any]([]T) {}
173func g2[T any]([]T, T) {}
174func g3[T any](*T, ...T) {}
175
176func _() {
177	type intSlize []int
178	g1([]int{})
179	g1(intSlize{})
180	g2(nil, 0)
181
182	type myString string
183	var s1 string
184	g3(nil, "1", myString("2"), "3")
185	g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3")
186	_ = s1
187
188	type myStruct struct{x int}
189	var s2 myStruct
190	g3(nil, struct{x int}{}, myStruct{})
191	g3(&s2, struct{x int}{}, myStruct{})
192	g3(nil, myStruct{}, struct{x int}{})
193	g3(&s2, myStruct{}, struct{x int}{})
194}
195
196// Here's a realistic example.
197
198func append[T any](s []T, t ...T) []T { panic(0) }
199
200func _() {
201	var f func()
202	type Funcs []func()
203	var funcs Funcs
204	_ = append(funcs, f)
205}
206
207// Generic type declarations cannot have empty type parameter lists
208// (that would indicate a slice type). Thus, generic functions cannot
209// have empty type parameter lists, either. This is a syntax error.
210
211func h[] /* ERROR empty type parameter list */ () {}
212
213func _() {
214	h[] /* ERROR operand */ ()
215}
216
217// Parameterized functions must have a function body.
218
219func _ /* ERROR missing function body */ [P any]()
220