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 generic types.
6
7 package p
8
9 // List is just what it says - a slice of E elements.
10 type List[E any] []E
11
12 // A generic (parameterized) type must always be instantiated
13 // before it can be used to designate the type of a variable
14 // (including a struct field, or function parameter); though
15 // for the latter cases, the provided type may be another type
16 // parameter. So:
17 var _ List[byte] = []byte{}
18
19 // A generic binary tree might be declared as follows.
20 type Tree[E any] struct {
21 left, right *Tree[E]
22 payload E
23 }
24
25 // A simple instantiation of Tree:
26 var root1 Tree[int]
27
28 // The actual type parameter provided may be a generic type itself:
29 var root2 Tree[List[int]]
30
31 // A couple of more complex examples.
32 // We don't need extra parentheses around the element type of the slices on
33 // the right (unlike when we use ()'s rather than []'s for type parameters).
34 var _ List[List[int]] = []List[int]{}
35 var _ List[List[List[Tree[int]]]] = []List[List[Tree[int]]]{}
36
37 // Type parameters act like type aliases when used in generic types
38 // in the sense that we can "emulate" a specific type instantiation
39 // with type aliases.
40 type T1[P any] struct {
41 f P
42 }
43
44 type T2[P any] struct {
45 f struct {
46 g P
47 }
48 }
49
50 var x1 T1[struct{ g int }]
51 var x2 T2[int]
52
53 func _() {
54 // This assignment is invalid because the types of x1, x2 are T1(...)
55 // and T2(...) respectively, which are two different defined types.
56 x1 = x2 // ERROR assignment
57
58 // This assignment is valid because the types of x1.f and x2.f are
59 // both struct { g int }; the type parameters act like type aliases
60 // and their actual names don't come into play here.
61 x1.f = x2.f
62 }
63
64 // We can verify this behavior using type aliases instead:
65 type T1a struct {
66 f A1
67 }
68 type A1 = struct { g int }
69
70 type T2a struct {
71 f struct {
72 g A2
73 }
74 }
75 type A2 = int
76
77 var x1a T1a
78 var x2a T2a
79
80 func _() {
81 x1a = x2a // ERROR assignment
82 x1a.f = x2a.f
83 }
84
85 // Another interesting corner case are generic types that don't use
86 // their type arguments. For instance:
87 type T[P any] struct{}
88
89 var xint T[int]
90 var xbool T[bool]
91
92 // Are these two variables of the same type? After all, their underlying
93 // types are identical. We consider them to be different because each type
94 // instantiation creates a new named type, in this case T<int> and T<bool>
95 // even if their underlying types are identical. This is sensible because
96 // we might still have methods that have different signatures or behave
97 // differently depending on the type arguments, and thus we can't possibly
98 // consider such types identical. Consequently:
99 func _() {
100 xint = xbool // ERROR assignment
101 }
102
103 // Generic types cannot be used without instantiation.
104 var _ T // ERROR cannot use generic type T
105 var _ = T /* ERROR cannot use generic type T */ (0)
106
107 // In type context, generic (parameterized) types cannot be parenthesized before
108 // being instantiated. See also NOTES entry from 12/4/2019.
109 var _ (T /* ERROR cannot use generic type T */ )[ /* ERROR expected ';' */ int]
110
111 // All types may be parameterized, including interfaces.
112 type I1[T any] interface{
113 m1(T)
114 }
115
116 // There is no such thing as a variadic generic type.
117 type _[T ... /* ERROR invalid use of ... */ any] struct{}
118
119 // Generic interfaces may be embedded as one would expect.
120 type I2 interface {
121 I1(int) // method!
122 I1[string] // embedded I1
123 }
124
125 func _() {
126 var x I2
127 x.I1(0)
128 x.m1("foo")
129 }
130
131 type I0 interface {
132 m0()
133 }
134
135 type I3 interface {
136 I0
137 I1[bool]
138 m(string)
139 }
140
141 func _() {
142 var x I3
143 x.m0()
144 x.m1(true)
145 x.m("foo")
146 }
147
148 // We accept parenthesized embedded struct fields so we can distinguish between
149 // a named field with a parenthesized type foo (T) and an embedded parameterized
150 // type (foo(T)), similarly to interface embedding.
151 // They still need to be valid embedded types after the parentheses are stripped
152 // (i.e., in contrast to interfaces, we cannot embed a struct literal). The name
153 // of the embedded field is derived as before, after stripping parentheses.
154 // (7/14/2020: See comment above. We probably will revert this generalized ability
155 // if we go with [] for type parameters.)
156 type _ struct {
157 int8
158 *int16
159 *List[int]
160
161 int8 /* ERROR int8 redeclared */
162 * /* ERROR List redeclared */ List[int]
163 }
164
165 // Issue #45639: We don't allow this anymore. Keep this code
166 // in case we decide to revisit this decision.
167 //
168 // It's possible to declare local types whose underlying types
169 // are type parameters. As with ordinary type definitions, the
170 // types underlying properties are "inherited" but the methods
171 // are not.
172 //func _[T interface{ m(); ~int }]() {
173 // type L T
174 // var x L
175 //
176 // // m is not defined on L (it is not "inherited" from
177 // // its underlying type).
178 // x.m /* ERROR x.m undefined */ ()
179 //
180 // // But the properties of T, such that as that it supports
181 // // the operations of the types given by its type bound,
182 // // are also the properties of L.
183 // x++
184 // _ = x - x
185 //
186 // // On the other hand, if we define a local alias for T,
187 // // that alias stands for T as expected.
188 // type A = T
189 // var y A
190 // y.m()
191 // _ = y < 0
192 //}
193
194 // For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
195 // // It is not permitted to declare a local type whose underlying
196 // // type is a type parameter not declared by that type declaration.
197 // func _[T any]() {
198 // type _ T // ERROR cannot use function type parameter T as RHS in type declaration
199 // type _ [_ any] T // ERROR cannot use function type parameter T as RHS in type declaration
200 // }
201
202 // As a special case, an explicit type argument may be omitted
203 // from a type parameter bound if the type bound expects exactly
204 // one type argument. In that case, the type argument is the
205 // respective type parameter to which the type bound applies.
206 // Note: We may not permit this syntactic sugar at first.
207 // Note: This is now disabled. All examples below are adjusted.
208 type Adder[T any] interface {
209 Add(T) T
210 }
211
212 // We don't need to explicitly instantiate the Adder bound
213 // if we have exactly one type parameter.
214 func Sum[T Adder[T]](list []T) T {
215 var sum T
216 for _, x := range list {
217 sum = sum.Add(x)
218 }
219 return sum
220 }
221
222 // Valid and invalid variations.
223 type B0 any
224 type B1[_ any] any
225 type B2[_, _ any] any
226
227 func _[T1 B0]() {}
228 func _[T1 B1[T1]]() {}
229 func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {}
230
231 func _[T1, T2 B0]() {}
232 func _[T1 B1[T1], T2 B1[T2]]() {}
233 func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]() {}
234
235 func _[T1 B0, T2 B1[T2]]() {} // here B1 applies to T2
236
237 // When the type argument is left away, the type bound is
238 // instantiated for each type parameter with that type
239 // parameter.
240 // Note: We may not permit this syntactic sugar at first.
241 func _[A Adder[A], B Adder[B], C Adder[A]]() {
242 var a A // A's type bound is Adder[A]
243 a = a.Add(a)
244 var b B // B's type bound is Adder[B]
245 b = b.Add(b)
246 var c C // C's type bound is Adder[A]
247 a = c.Add(a)
248 }
249
250 // The type of variables (incl. parameters and return values) cannot
251 // be an interface with type constraints or be/embed comparable.
252 type I interface {
253 ~int
254 }
255
256 var (
257 _ interface /* ERROR contains type constraints */ {~int}
258 _ I /* ERROR contains type constraints */
259 )
260
261 func _(I /* ERROR contains type constraints */ )
262 func _(x, y, z I /* ERROR contains type constraints */ )
263 func _() I /* ERROR contains type constraints */
264
265 func _() {
266 var _ I /* ERROR contains type constraints */
267 }
268
269 type C interface {
270 comparable
271 }
272
273 var _ comparable /* ERROR comparable */
274 var _ C /* ERROR comparable */
275
276 func _(_ comparable /* ERROR comparable */ , _ C /* ERROR comparable */ )
277
278 func _() {
279 var _ comparable /* ERROR comparable */
280 var _ C /* ERROR comparable */
281 }
282
283 // Type parameters are never const types, i.e., it's
284 // not possible to declare a constant of type parameter type.
285 // (If a type set contains just a single const type, we could
286 // allow it, but such type sets don't make much sense in the
287 // first place.)
288 func _[T interface {~int|~float64}]() {
289 // not valid
290 const _ = T /* ERROR not constant */ (0)
291 const _ T /* ERROR invalid constant type T */ = 1
292
293 // valid
294 var _ = T(0)
295 var _ T = 1
296 _ = T(0)
297 }
298
299 // It is possible to create composite literals of type parameter
300 // type as long as it's possible to create a composite literal
301 // of the core type of the type parameter's constraint.
302 func _[P interface{ ~[]int }]() P {
303 return P{}
304 return P{1, 2, 3}
305 }
306
307 func _[P interface{ ~[]E }, E interface{ map[string]P } ]() P {
308 x := P{}
309 return P{{}}
310 return P{E{}}
311 return P{E{"foo": x}}
312 return P{{"foo": x}, {}}
313 }
314
315 // This is a degenerate case with a singleton type set, but we can create
316 // composite literals even if the core type is a defined type.
317 type MyInts []int
318
319 func _[P MyInts]() P {
320 return P{}
321 }
322
View as plain text