github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/typeparams/example/generic-go-types.md (about) 1 <!-- To regenerate the readme, run: --> 2 <!-- go run golang.org/x/example/gotypes@latest generic-go-types.md --> 3 4 # Updating tools to support type parameters. 5 6 This guide is maintained by Rob Findley (`rfindley@google.com`). 7 8 **status**: this document is currently a work-in-progress. See 9 [golang/go#50447](https://go.dev/issues/50447) for more details. 10 11 %toc 12 13 # Introduction 14 15 With Go 1.18, Go now supports generic programming via type parameters. This 16 document is intended to serve as a guide for tool authors that want to update 17 their tools to support the new language constructs introduced for generic Go. 18 19 This guide assumes some knowledge of the language changes to support generics. 20 See the following references for more information: 21 22 - The [original proposal](https://go.dev/issue/43651) for type parameters. 23 - The [addendum for type sets](https://go.dev/issue/45346). 24 - The [latest language specfication](https://tip.golang.org/ref/spec) (still in-progress as of 2021-01-11). 25 - The proposals for new APIs in 26 [go/token and go/ast](https://go.dev/issue/47781), and in 27 [go/types](https://go.dev/issue/47916). 28 29 It also assumes existing knowledge of `go/ast` and `go/types`. If you're just 30 getting started, 31 [x/example/gotypes](https://github.com/golang/example/tree/master/gotypes) is 32 a great introduction (and was the inspiration for this guide). 33 34 # Summary of new language features and their APIs 35 36 While generic Go programming is a large change to the language, at a high level 37 it introduces only a few new concepts. Specifically, we can break down our 38 discussion into the following three broad categories. In each category, the 39 relevant new APIs are listed (some constructors and getters/setters may be 40 elided where they are trivial). 41 42 **Generic types**. Types and functions may be _generic_, meaning their 43 declaration has a non-empty _type parameter list_: as in `type List[T any] 44 ...` or `func f[T1, T2 any]() { ... }`. Type parameter lists define placeholder 45 types (_type parameters_), scoped to the declaration, which may be substituted 46 by any type satisfying their corresponding _constraint interface_ to 47 _instantiate_ a new type or function. 48 49 Generic types may have methods, which declare `receiver type parameters` via 50 their receiver type expression: `func (r T[P1, ..., PN]) method(...) (...) 51 {...}`. 52 53 _New APIs_: 54 - The field `ast.TypeSpec.TypeParams` holds the type parameter list syntax for 55 type declarations. 56 - The field `ast.FuncType.TypeParams` holds the type parameter list syntax for 57 function declarations. 58 - The type `types.TypeParam` is a `types.Type` representing a type parameter. 59 On this type, the `Constraint` and `SetConstraint` methods allow 60 getting/setting the constraint, the `Index` method returns the index of the 61 type parameter in the type parameter list that declares it, and the `Obj` 62 method returns the object declared in the declaration scope for the type 63 parameter (a `types.TypeName`). 64 - The type `types.TypeParamList` holds a list of type parameters. 65 - The method `types.Named.TypeParams` returns the type parameters for a type 66 declaration. 67 - The method `types.Named.SetTypeParams` sets type parameters on a defined 68 type. 69 - The function `types.NewSignatureType` creates a new (possibly generic) 70 signature type. 71 - The method `types.Signature.RecvTypeParams` returns the receiver type 72 parameters for a method. 73 - The method `types.Signature.TypeParams` returns the type parameters for 74 a function. 75 76 **Constraint Interfaces**: type parameter constraints are interfaces, expressed 77 via an interface type expression. Interfaces that are only used in constraint 78 position are permitted new embedded elements composed of tilde expressions 79 (`~T`) and unions (`A | B | ~C`). The new builtin interface type `comparable` 80 is implemented by types for which `==` and `!=` are valid. As a special case, 81 the `interface` keyword may be omitted from constraint expressions if it may be 82 implied (in which case we say the interface is _implicit_). 83 84 _New APIs_: 85 - The constant `token.TILDE` is used to represent tilde expressions as an 86 `ast.UnaryExpr`. 87 - Union expressions are represented as an `ast.BinaryExpr` using `|`. This 88 means that `ast.BinaryExpr` may now be both a type and value expression. 89 - The method `types.Interface.IsImplicit` reports whether the `interface` 90 keyword was elided from this interface. 91 - The method `types.Interface.MarkImplicit` marks an interface as being 92 implicit. 93 - The method `types.Interface.IsComparable` reports whether every type in an 94 interface's type set is comparable. 95 - The method `types.Interface.IsMethodSet` reports whether an interface is 96 defined entirely by its methods (has no _specific types_). 97 - The type `types.Union` is a type that represents an embedded union 98 expression in an interface. May only appear as an embedded element in 99 interfaces. 100 - The type `types.Term` represents a (possibly tilde) term of a union. 101 102 **Instantiation**: generic types and functions may be _instantiated_ to create 103 non-generic types and functions by providing _type arguments_ (`var x T[int]`). 104 Function type arguments may be _inferred_ via function arguments, or via 105 type parameter constraints. 106 107 _New APIs_: 108 - The type `ast.IndexListExpr` holds index expressions with multiple indices, 109 as occurs in instantiation expressions with multiple type arguments, or in 110 receivers with multiple type parameters. 111 - The function `types.Instantiate` instantiates a generic type with type arguments. 112 - The type `types.Context` is an opaque instantiation context that may be 113 shared to reduce duplicate instances. 114 - The field `types.Config.Context` holds a shared `Context` to use for 115 instantiation while type-checking. 116 - The type `types.TypeList` holds a list of types. 117 - The type `types.ArgumentError` holds an error associated with a specific 118 argument index. Used to represent instantiation errors. 119 - The field `types.Info.Instances` maps instantiated identifiers to information 120 about the resulting type instance. 121 - The type `types.Instance` holds information about a type or function 122 instance. 123 - The method `types.Named.TypeArgs` reports the type arguments used to 124 instantiate a named type. 125 126 # Examples 127 128 The following examples demonstrate the new APIs above, and discuss their 129 properties. All examples are runnable, contained in subdirectories of the 130 directory holding this README. 131 132 ## Generic types 133 134 ### Type parameter lists 135 136 Suppose we want to understand the generic library below, which defines a generic 137 `Pair`, a constraint interface `Constraint`, and a generic function `MakePair`. 138 139 %include findtypeparams/main.go input - 140 141 We can use the new `TypeParams` fields in `ast.TypeSpec` and `ast.FuncType` to 142 access the syntax of the type parameter list. From there, we can access type 143 parameter types in at least three ways: 144 - by looking up type parameter definitions in `types.Info` 145 - by calling `TypeParams()` on `types.Named` or `types.Signature` 146 - by looking up type parameter objects in the declaration scope. Note that 147 there now may be a scope associated with an `ast.TypeSpec` node. 148 149 %include findtypeparams/main.go print - 150 151 This program produces the following output. Note that not every type spec has 152 a scope. 153 154 %include findtypeparams/main.go output - 155 156 ### Methods on generic types 157 158 **TODO** 159 160 ## Constraint Interfaces 161 162 ### New interface elements 163 164 **TODO** 165 166 ### Implicit interfaces 167 168 **TODO** 169 170 ### Type sets 171 172 **TODO** 173 174 ## Instantiation 175 176 ### Finding instantiated types 177 178 **TODO** 179 180 ### Creating new instantiated types 181 182 **TODO** 183 184 ### Using a shared context 185 186 **TODO** 187 188 # Updating tools while building at older Go versions 189 190 In the examples above, we can see how a lot of the new APIs integrate with 191 existing usage of `go/ast` or `go/types`. However, most tools still need to 192 build at older Go versions, and handling the new language constructs in-line 193 will break builds at older Go versions. 194 195 For this purpose, the `x/exp/typeparams` package provides functions and types 196 that proxy the new APIs (with stub implementations at older Go versions). 197 **NOTE**: does not yet exist -- see 198 [golang/go#50447](https://go.dev/issues/50447) for more information. 199 200 # Further help 201 202 If you're working on updating a tool to support generics, and need help, please 203 feel free to reach out for help in any of the following ways: 204 - Via the [golang-tools](https://groups.google.com/g/golang-tools) mailing list. 205 - Directly to me via email (`rfindley@google.com`). 206 - For bugs, you can [file an issue](https://github.com/golang/go/issues/new/choose).