Text file src/go/types/testdata/examples/types.go2

     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