design: promote type parameters to a proposal

Associate it with the issue number. Stop referring to it as a draft.

For golang/go#43651

Change-Id: Id5db4a80b7d8a21d4028c31b5348b6492fe96074
Reviewed-on: https://go-review.googlesource.com/c/proposal/+/303389
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/design/43651-type-parameters.md b/design/43651-type-parameters.md
new file mode 100644
index 0000000..6c361f0
--- /dev/null
+++ b/design/43651-type-parameters.md
@@ -0,0 +1,4002 @@
+# Type Parameters Proposal
+
+Ian Lance Taylor\
+Robert Griesemer\
+March 19, 2021
+
+## Status
+
+This is the design for adding generic programming using type
+parameters to the Go language.
+This design has been [proposed and
+accepted](https://golang.org/issue/43651) as a future language change.
+We currently expect that this change will be available in the Go 1.18
+release in early 2022.
+
+## Abstract
+
+We suggest extending the Go language to add optional type parameters
+to type and function declarations.
+Type parameters are constrained by interface types.
+Interface types, when used as type constraints, permit listing the set
+of types that may be assigned to them.
+Type inference via a unification algorithm permits omitting type
+arguments from function calls in many cases.
+The design is fully backward compatible with Go 1.
+
+## How to read this proposal
+
+This document is long.
+Here is some guidance on how to read it.
+
+* We start with a high level overview, describing the concepts very
+  briefly.
+* We then explain the full design starting from scratch, introducing
+  the details as we need them, with simple examples.
+* After the design is completely described, we discuss implementation,
+  some issues with the design, and a comparison with other approaches
+  to generics.
+* We then present several complete examples of how this design would
+  be used in practice.
+* Following the examples some minor details are discussed in an
+  appendix.
+
+## Very high level overview
+
+This section explains the changes suggested by the design very
+briefly.
+This section is intended for people who are already familiar with how
+generics would work in a language like Go.
+These concepts will be explained in detail in the following sections.
+
+* Functions can have an additional type parameter list that uses
+  square brackets but otherwise looks like an ordinary parameter list:
+  `func F[T any](p T) { ... }`.
+* These type parameters can be used by the regular parameters and in
+  the function body.
+* Types can also have a type parameter list: `type M[T any] []T`.
+* Each type parameter has a type constraint, just as each ordinary
+  parameter has a type: `func F[T Constraint](p T) { ... }`.
+* Type constraints are interface types.
+* The new predeclared name `any` is a type constraint that permits any
+  type.
+* Interface types used as type constraints can have a list of
+  predeclared types; only type arguments that match one of those types
+  satisfy the constraint.
+* Generic functions may only use operations permitted by the type
+  constraint.
+* Using a generic function or type requires passing type arguments.
+* Type inference permits omitting the type arguments of a function
+  call in common cases.
+
+In the following sections we work through each of these language
+changes in great detail.
+You may prefer to skip ahead to the [examples](#Examples) to see what
+generic code written to this design will look like in practice.
+
+## Background
+
+There have been many [requests to add additional support for generic
+programming](https://github.com/golang/go/wiki/ExperienceReports#generics)
+in Go.
+There has been extensive discussion on
+[the issue tracker](https://golang.org/issue/15292) and on
+[a living document](https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/view).
+
+This design suggests extending the Go language to add a form of
+parametric polymorphism, where the type parameters are bounded not by
+a declared subtyping relationship (as in some object oriented
+languages) but by explicitly defined structural constraints.
+
+This version of the design has many similarities to a design draft
+presented on July 31, 2019, but contracts have been removed and
+replaced by interface types, and the syntax has changed.
+
+There have been several proposals for adding type parameters, which
+can be found through the links above.
+Many of the ideas presented here have appeared before.
+The main new features described here are the syntax and the careful
+examination of interface types as constraints.
+
+This design does not support template metaprogramming or any other
+form of compile time programming.
+
+As the term _generic_ is widely used in the Go community, we will
+use it below as a shorthand to mean a function or type that takes type
+parameters.
+Don't confuse the term generic as used in this design with the same
+term in other languages like C++, C#, Java, or Rust; they have
+similarities but are not the same.
+
+## Design
+
+We will describe the complete design in stages based on simple
+examples.
+
+### Type parameters
+
+Generic code is written using abstract data types that we call _type
+parameters_.
+When running the generic code, the type parameters are replaced by
+_type arguments_.
+
+Here is a function that prints out each element of a slice, where the
+element type of the slice, here called `T`, is unknown.
+This is a trivial example of the kind of function we want to permit in
+order to support generic programming.
+(Later we'll also discuss [generic types](#Generic-types)).
+
+```
+// Print prints the elements of a slice.
+// It should be possible to call this with any slice value.
+func Print(s []T) { // Just an example, not the suggested syntax.
+	for _, v := range s {
+		fmt.Println(v)
+	}
+}
+```
+
+With this approach, the first decision to make is: how should the type
+parameter `T` be declared?
+In a language like Go, we expect every identifier to be declared in
+some way.
+
+Here we make a design decision: type parameters are similar to
+ordinary non-type function parameters, and as such should be listed
+along with other parameters.
+However, type parameters are not the same as non-type parameters, so
+although they appear in the list of parameters we want to distinguish
+them.
+That leads to our next design decision: we define an additional
+optional parameter list describing type parameters.
+
+This type parameter list appears before the regular parameters.
+To distinguish the type parameter list from the regular parameter
+list, the type parameter list uses square brackets rather than
+parentheses.
+Just as regular parameters have types, type parameters have
+meta-types, also known as constraints.
+We will discuss the details of constraints later; for now, we will
+just note that `any` is a valid constraint, meaning that any type is
+permitted.
+
+```
+// Print prints the elements of any slice.
+// Print has a type parameter T and has a single (non-type)
+// parameter s which is a slice of that type parameter.
+func Print[T any](s []T) {
+	// same as above
+}
+```
+
+This says that within the function `Print` the identifier `T` is a
+type parameter, a type that is currently unknown but that will be
+known when the function is called.
+The `any` means that `T` can be any type at all.
+As seen above, the type parameter may be used as a type when
+describing the types of the ordinary non-type parameters.
+It may also be used as a type within the body of the function.
+
+Unlike regular parameter lists, in type parameter lists names are
+required for the type parameters.
+This avoids a syntactic ambiguity, and, as it happens, there is no
+reason to ever omit the type parameter names.
+
+Since `Print` has a type parameter, any call of `Print` must provide a
+type argument.
+Later we will see how this type argument can usually be deduced from
+the non-type argument, by using [type inference](#Type-inference).
+For now, we'll pass the type argument explicitly.
+Type arguments are passed much like type parameters are declared: as a
+separate list of arguments.
+As with the type parameter list, the list of type arguments uses
+square brackets.
+
+```
+	// Call Print with a []int.
+	// Print has a type parameter T, and we want to pass a []int,
+	// so we pass a type argument of int by writing Print[int].
+	// The function Print[int] expects a []int as an argument.
+	Print[int]([]int{1, 2, 3})
+
+	// This will print:
+	// 1
+	// 2
+	// 3
+```
+
+### Constraints
+
+Let's make our example slightly more complicated.
+Let's turn it into a function that converts a slice of any type into a
+`[]string` by calling a `String` method on each element.
+
+```
+// This function is INVALID.
+func Stringify[T any](s []T) (ret []string) {
+	for _, v := range s {
+		ret = append(ret, v.String()) // INVALID
+	}
+	return ret
+}
+```
+
+This might seem OK at first glance, but in this example `v` has type
+`T`, and `T` can be any type.
+This means that `T` need not have a `String` method.
+So the call to `v.String()` is invalid.
+
+Naturally, the same issue arises in other languages that support
+generic programming.
+In C++, for example, a generic function (in C++ terms, a function
+template) can call any method on a value of generic type.
+That is, in the C++ approach, calling `v.String()` is fine.
+If the function is called with a type argument that does not have a
+`String` method, the error is reported when compiling the call to
+`v.String` with that type argument.
+These errors can be lengthy, as there may be several layers of generic
+function calls before the error occurs, all of which must be reported
+to understand what went wrong.
+
+The C++ approach would be a poor choice for Go.
+One reason is the style of the language.
+In Go we don't refer to names, such as, in this case, `String`, and
+hope that they exist.
+Go resolves all names to their declarations when they are seen.
+
+Another reason is that Go is designed to support programming at
+scale.
+We must consider the case in which the generic function definition
+(`Stringify`, above) and the call to the generic function (not shown,
+but perhaps in some other package) are far apart.
+In general, all generic code expects the type arguments to meet
+certain requirements.
+We refer to these requirements as _constraints_ (other languages have
+similar ideas known as type bounds or trait bounds or concepts).
+In this case, the constraint is pretty obvious: the type has to have a
+`String() string` method.
+In other cases it may be much less obvious.
+
+We don't want to derive the constraints from whatever `Stringify`
+happens to do (in this case, call the `String` method).
+If we did, a minor change to `Stringify` might change the
+constraints.
+That would mean that a minor change could cause code far away, that
+calls the function, to unexpectedly break.
+It's fine for `Stringify` to deliberately change its constraints, and
+force callers to change.
+What we want to avoid is `Stringify` changing its constraints
+accidentally.
+
+This means that the constraints must set limits on both the type
+arguments passed by the caller and the code in the generic function.
+The caller may only pass type arguments that satisfy the constraints.
+The generic function may only use those values in ways that are
+permitted by the constraints.
+This is an important rule that we believe should apply to any attempt
+to define generic programming in Go: generic code can only use
+operations that its type arguments are known to implement.
+
+### Operations permitted for any type
+
+Before we discuss constraints further, let's briefly note what happens
+when the constraint is `any`.
+If a generic function uses the `any` constraint for a type parameter,
+as is the case for the `Print` method above, then any type argument is
+permitted for that parameter.
+The only operations that the generic function can use with values of
+that type parameter are those operations that are permitted for values
+of any type.
+In the example above, the `Print` function declares a variable `v`
+whose type is the type parameter `T`, and it passes that variable to a
+function.
+
+The operations permitted for any type are:
+
+* declare variables of those types
+* assign other values of the same type to those variables
+* pass those variables to functions or return them from functions
+* take the address of those variables
+* convert or assign values of those types to the type `interface{}`
+* convert a value of type `T` to type `T` (permitted but useless)
+* use a type assertion to convert an interface value to the type
+* use the type as a case in a type switch
+* define and use composite types that use those types, such as a slice
+  of that type
+* pass the type to some predeclared functions such as `new`
+
+It's possible that future language changes will add other such
+operations, though none are currently anticipated.
+
+### Defining constraints
+
+Go already has a construct that is close to what we need for a
+constraint: an interface type.
+An interface type is a set of methods.
+The only values that can be assigned to a variable of interface type
+are those whose types implement the same methods.
+The only operations that can be done with a value of interface type,
+other than operations permitted for any type, are to call the
+methods.
+
+Calling a generic function with a type argument is similar to
+assigning to a variable of interface type: the type argument must
+implement the constraints of the type parameter.
+Writing a generic function is like using values of interface type: the
+generic code can only use the operations permitted by the constraint
+(or operations that are permitted for any type).
+
+Therefore, in this design, constraints are simply interface types.
+Implementing a constraint means implementing the interface type.
+(Later we'll see how to define constraints for operations other than
+method calls, such as [binary operators](#Operators)).
+
+For the `Stringify` example, we need an interface type with a `String`
+method that takes no arguments and returns a value of type `string`.
+
+```
+// Stringer is a type constraint that requires the type argument to have
+// a String method and permits the generic function to call String.
+// The String method should return a string representation of the value.
+type Stringer interface {
+	String() string
+}
+```
+
+(It doesn't matter for this discussion, but this defines the same
+interface as the standard library's `fmt.Stringer` type, and  real
+code would likely simply use `fmt.Stringer`.)
+
+### The `any` constraint
+
+Now that we know that constraints are simply interface types, we can
+explain what `any` means as a constraint.
+As shown above, the `any` constraint permits any type as a type
+argument and only permits the function to use the operations permitted
+for any type.
+The interface type for that is the empty interface: `interface{}`.
+So we could write the `Print` example as
+
+```
+// Print prints the elements of any slice.
+// Print has a type parameter T and has a single (non-type)
+// parameter s which is a slice of that type parameter.
+func Print[T interface{}](s []T) {
+	// same as above
+}
+```
+
+However, it's tedious to have to write `interface{}` every time you
+write a generic function that doesn't impose constraints on its type
+parameters.
+So in this design we suggest a type constraint `any` that is
+equivalent to `interface{}`.
+This will be a predeclared name, implicitly declared in the universe
+block.
+It will not be valid to use `any` as anything other than a type
+constraint.
+
+(Note: clearly we could make `any` generally available as an alias for
+`interface{}`, or as a new defined type defined as `interface{}`.
+However, we don't want this design, which is about generics, to lead
+to a possibly significant change to non-generic code.
+Adding `any` as a general purpose name for `interface{}` can and
+should be [discussed separately](https://golang.org/issue/33232)).
+
+### Using a constraint
+
+For a generic function, a constraint can be thought of as the type of
+the type argument: a meta-type.
+As shown above, constraints appear in the type parameter list as the
+meta-type of a type parameter.
+
+```
+// Stringify calls the String method on each element of s,
+// and returns the results.
+func Stringify[T Stringer](s []T) (ret []string) {
+	for _, v := range s {
+		ret = append(ret, v.String())
+	}
+	return ret
+}
+```
+
+The single type parameter `T` is followed by the constraint that
+applies to `T`, in this case `Stringer`.
+
+### Multiple type parameters
+
+Although the `Stringify` example uses only a single type parameter,
+functions may have multiple type parameters.
+
+```
+// Print2 has two type parameters and two non-type parameters.
+func Print2[T1, T2 any](s1 []T1, s2 []T2) { ... }
+```
+
+Compare this to
+
+```
+// Print2Same has one type parameter and two non-type parameters.
+func Print2Same[T any](s1 []T, s2 []T) { ... }
+```
+
+In `Print2` `s1` and `s2` may be slices of different types.
+In `Print2Same` `s1` and `s2` must be slices of the same element
+type.
+
+Just as each ordinary parameter may have its own type, each type
+parameter may have its own constraint.
+
+```
+// Stringer is a type constraint that requires a String method.
+// The String method should return a string representation of the value.
+type Stringer interface {
+	String() string
+}
+
+// Plusser is a type constraint that requires a Plus method.
+// The Plus method is expected to add the argument to an internal
+// string and return the result.
+type Plusser interface {
+	Plus(string) string
+}
+
+// ConcatTo takes a slice of elements with a String method and a slice
+// of elements with a Plus method. The slices should have the same
+// number of elements. This will convert each element of s to a string,
+// pass it to the Plus method of the corresponding element of p,
+// and return a slice of the resulting strings.
+func ConcatTo[S Stringer, P Plusser](s []S, p []P) []string {
+	r := make([]string, len(s))
+	for i, v := range s {
+		r[i] = p[i].Plus(v.String())
+	}
+	return r
+}
+```
+
+A single constraint can be used for multiple type parameters, just as
+a single type can be used for multiple non-type function parameters.
+The constraint applies to each type parameter separately.
+
+```
+// Stringify2 converts two slices of different types to strings,
+// and returns the concatenation of all the strings.
+func Stringify2[T1, T2 Stringer](s1 []T1, s2 []T2) string {
+	r := ""
+	for _, v1 := range s1 {
+		r += v1.String()
+	}
+	for _, v2 := range s2 {
+		r += v2.String()
+	}
+	return r
+}
+```
+
+### Generic types
+
+We want more than just generic functions: we also want generic types.
+We suggest that types be extended to take type parameters.
+
+```
+// Vector is a name for a slice of any element type.
+type Vector[T any] []T
+```
+
+A type's type parameters are just like a function's type parameters.
+
+Within the type definition, the type parameters may be used like any
+other type.
+
+To use a generic type, you must supply type arguments.
+This is called _instantiation_.
+The type arguments appear in square brackets, as usual.
+When we instantiate a type by supplying type arguments for the type
+parameters, we produce a type in which each use of a type parameter in
+the type definition is replaced by the corresponding type argument.
+
+```
+// v is a Vector of int values.
+//
+// This is similar to pretending that "Vector[int]" is a valid identifier,
+// and writing
+//   type "Vector[int]" []int
+//   var v "Vector[int]"
+// All uses of Vector[int] will refer to the same "Vector[int]" type.
+//
+var v Vector[int]
+```
+
+Generic types can have methods.
+The receiver type of a method must declare the same number of type
+parameters as are declared in the receiver type's definition.
+They are declared without any constraint.
+
+```
+// Push adds a value to the end of a vector.
+func (v *Vector[T]) Push(x T) { *v = append(*v, x) }
+```
+
+The type parameters listed in a method declaration need not have the
+same names as the type parameters in the type declaration.
+In particular, if they are not used by the method, they can be `_`.
+
+A generic type can refer to itself in cases where a type can
+ordinarily refer to itself, but when it does so the type arguments
+must be the type parameters, listed in the same order.
+This restriction prevents infinite recursion of type instantiation.
+
+```
+// List is a linked list of values of type T.
+type List[T any] struct {
+	next *List[T] // this reference to List[T] is OK
+	val  T
+}
+
+// This type is INVALID.
+type P[T1, T2 any] struct {
+	F *P[T2, T1] // INVALID; must be [T1, T2]
+}
+```
+
+This restriction applies to both direct and indirect references.
+
+```
+// ListHead is the head of a linked list.
+type ListHead[T any] struct {
+	head *ListElement[T]
+}
+
+// ListElement is an element in a linked list with a head.
+// Each element points back to the head.
+type ListElement[T any] struct {
+	next *ListElement[T]
+	val  T
+	// Using ListHead[T] here is OK.
+	// ListHead[T] refers to ListElement[T] refers to ListHead[T].
+	// Using ListHead[int] would not be OK, as ListHead[T]
+	// would have an indirect reference to ListHead[int].
+	head *ListHead[T]
+}
+```
+
+(Note: with more understanding of how people want to write code, it
+may be possible to relax this rule to permit some cases that use
+different type arguments.)
+
+The type parameter of a generic type may have constraints other than
+`any`.
+
+```
+// StringableVector is a slice of some type, where the type
+// must have a String method.
+type StringableVector[T Stringer] []T
+
+func (s StringableVector[T]) String() string {
+	var sb strings.Builder
+	for i, v := range s {
+		if i > 0 {
+			sb.WriteString(", ")
+		}
+		// It's OK to call v.String here because v is of type T
+		// and T's constraint is Stringer.
+		sb.WriteString(v.String())
+	}
+	return sb.String()
+}
+```
+
+### Methods may not take additional type arguments
+
+Although methods of a generic type may use the type's parameters,
+methods may not themselves have additional type parameters.
+Where it would be useful to add type arguments to a method, people
+will have to write a suitably parameterized top-level function.
+
+There is more discussion of this in [the issues
+section](#No-parameterized-methods).
+
+### Operators
+
+As we've seen, we are using interface types as constraints.
+Interface types provide a set of methods, and nothing else.
+This means that with what we've seen so far, the only thing that
+generic functions can do with values of type parameters, other than
+operations that are permitted for any type, is call methods.
+
+However, method calls are not sufficient for everything we want to
+express.
+Consider this simple function that returns the smallest element of a
+slice of values, where the slice is assumed to be non-empty.
+
+```
+// This function is INVALID.
+func Smallest[T any](s []T) T {
+	r := s[0] // panic if slice is empty
+	for _, v := range s[1:] {
+		if v < r { // INVALID
+			r = v
+		}
+	}
+	return r
+}
+```
+
+Any reasonable generics implementation should let you write this
+function.
+The problem is the expression `v < r`.
+This assumes that `T` supports the `<` operator, but the constraint on
+`T` is simply `any`.
+With the `any` constraint the function `Smallest` can only use
+operations that are available for all types, but not all Go types
+support `<`.
+Unfortunately, since `<` is not a method, there is no obvious way to
+write a constraint&mdash;an interface type&mdash;that permits `<`.
+
+We need a way to write a constraint that accepts only types that
+support `<`.
+In order to do that, we observe that, aside from two exceptions that
+we will discuss later, all the arithmetic, comparison, and logical
+operators defined by the language may only be used with types that are
+predeclared by the language, or with defined types whose underlying
+type is one of those predeclared types.
+That is, the operator `<` can only be used with a predeclared type
+such as `int` or `float64`, or a defined type whose underlying type is
+one of those types.
+Go does not permit using `<` with a composite type or with an
+arbitrary defined type.
+
+This means that rather than try to write a constraint for `<`, we can
+approach this the other way around: instead of saying which operators
+a constraint should support, we can say which (underlying) types a
+constraint should accept.
+
+#### Type lists in constraints
+
+An interface type used as a constraint may list explicit types that
+may be used as type arguments.
+This is done using the `type` keyword followed by a comma-separated
+list of types.
+
+For example:
+
+```
+// SignedInteger is a type constraint that permits any
+// signed integer type.
+type SignedInteger interface {
+	type int, int8, int16, int32, int64
+}
+```
+
+The `SignedInteger` constraint specifies that the type argument
+must be one of the listed types.
+More precisely, either the type argument or the underlying type of the
+type argument must be identical to one of the types in the type list.
+This means that `SignedInteger` will accept the listed integer types,
+and will also accept any type that is defined as one of those types.
+
+When a generic function uses a type parameter with one of these
+constraints, it may use it in any way that is permitted by all of the
+listed types.
+This could mean operators like `<`, `<-`, or use in a `range` loop, or
+in general any language construct.
+If the function can be compiled successfully using each type listed in
+the constraint, then the use is permitted.
+
+A constraint may only have one type list.
+
+For the `Smallest` example shown earlier, we could use a constraint
+like this:
+
+```
+package constraints
+
+// Ordered is a type constraint that matches any ordered type.
+// An ordered type is one that supports the <, <=, >, and >= operators.
+type Ordered interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr,
+		float32, float64,
+		string
+}
+```
+
+In practice this constraint would likely be defined and exported in a
+new standard library package, `constraints`, so that it could be used
+by function and type definitions.
+
+Given that constraint, we can write this function, now valid:
+
+```
+// Smallest returns the smallest element in a slice.
+// It panics if the slice is empty.
+func Smallest[T constraints.Ordered](s []T) T {
+	r := s[0] // panics if slice is empty
+	for _, v := range s[1:] {
+		if v < r {
+			r = v
+		}
+	}
+	return r
+}
+```
+
+#### Comparable types in constraints
+
+Earlier we mentioned that there are two exceptions to the rule that
+operators may only be used with types that are predeclared by the
+language.
+The exceptions are `==` and `!=`, which are permitted for struct,
+array, and interface types.
+These are useful enough that we want to be able to write a constraint
+that accepts any comparable type.
+
+To do this we introduce a new predeclared type constraint:
+`comparable`.
+A type parameter with the `comparable` constraint accepts as a type
+argument any comparable type.
+It permits the use of `==` and `!=` with values of that type parameter.
+
+For example, this function may be instantiated with any comparable
+type:
+
+```
+// Index returns the index of x in s, or -1 if not found.
+func Index[T comparable](s []T, x T) int {
+	for i, v := range s {
+		// v and x are type T, which has the comparable
+		// constraint, so we can use == here.
+		if v == x {
+			return i
+		}
+	}
+	return -1
+}
+```
+
+Since `comparable`, like all constraints, is an interface type, it can
+be embedded in another interface type used as a constraint:
+
+```
+// ComparableHasher is a type constraint that matches all
+// comparable types with a Hash method.
+type ComparableHasher interface {
+	comparable
+	Hash() uintptr
+}
+```
+
+The constraint `ComparableHasher` is implemented by any type that is
+comparable and also has a `Hash() uintptr` method.
+A generic function that uses `ComparableHasher` as a constraint can
+compare values of that type and can call the `Hash` method.
+
+It's possible to use `comparable` to produce a constraint that can not
+be satisfied by any type.
+
+```
+// ImpossibleConstraint is a type constraint that no type can satisfy,
+// because slice types are not comparable.
+type ImpossibleConstraint interface {
+	comparable
+	type []int
+}
+```
+
+This is not in itself an error, but of course there is no way to
+instantiate a type parameter that uses such a constraint.
+
+#### Type lists in interface types
+
+Interface types with type lists may only be used as constraints on
+type parameters.
+They may not be used as ordinary interface types.
+The same is true of the predeclared interface type `comparable`.
+
+This restriction may be lifted in future language versions.
+An interface type with a type list may be useful as a form of sum
+type, albeit one that can have the value `nil`.
+
+A type argument satisfies a type constraint with a type list if the
+type argument or its underlying type is present in that type list.
+If in some future language version we permit interface types with type
+lists outside of type constraints, this rule will make them usable
+both as type constraints and as sum types.
+Using a list of defined types would mean that only those exact types
+would implement the interface, which is to say that only those exact
+types could be assigned to the sum type.
+Using a list of predeclared types and/or type literals would mean that
+any type defined as one of those types would implement the interface
+or be assignable to the sum type.
+There would be no way to write a sum type to accept only a predeclared
+type or type literal and reject types defined as those types.
+That restriction is likely acceptable for the cases where people want
+to use sum types.
+
+### Mutually referencing type parameters
+
+Within a single type parameter list, constraints may refer to any of
+the other type parameters, even ones that are declared later in the
+same list.
+(The scope of a type parameter starts at the beginning of the type
+parameter list and extends to the end of the enclosing function or
+type declaration.)
+
+For example, consider a generic graph package that contains generic
+algorithms that work with graphs.
+The algorithms use two types, `Node` and `Edge`.
+`Node` is expected to have a method `Edges() []Edge`.
+`Edge` is expected to have a method `Nodes() (Node, Node)`.
+A graph can be represented as a `[]Node`.
+
+This simple representation is enough to implement graph algorithms
+like finding the shortest path.
+
+```
+package graph
+
+// NodeConstraint is the type constraint for graph nodes:
+// they must have an Edges method that returns the Edge's
+// that connect to this Node.
+type NodeConstraint[Edge any] interface {
+	Edges() []Edge
+}
+
+// EdgeConstraint is the type constraint for graph edges:
+// they must have a Nodes method that returns the two Nodes
+// that this edge connects.
+type EdgeConstraint[Node any] interface {
+	Nodes() (from, to Node)
+}
+
+// Graph is a graph composed of nodes and edges.
+type Graph[Node NodeConstraint[Edge], Edge EdgeConstraint[Node]] struct { ... }
+
+// New returns a new graph given a list of nodes.
+func New[Node NodeConstraint[Edge], Edge EdgeConstraint[Node]] (nodes []Node) *Graph[Node, Edge] {
+	...
+}
+
+// ShortestPath returns the shortest path between two nodes,
+// as a list of edges.
+func (g *Graph[Node, Edge]) ShortestPath(from, to Node) []Edge { ... }
+```
+
+There are a lot of type arguments and instantiations here.
+In the constraint on `Node` in `Graph`, the `Edge` being passed to the
+type constraint `NodeConstraint` is the second type parameter of
+`Graph`.
+This instantiates `NodeConstraint` with the type parameter `Edge`, so
+we see that `Node` must have a method `Edges` that returns a slice of
+`Edge`, which is what we want.
+The same applies to the constraint on `Edge`, and the same type
+parameters and constraints are repeated for the function `New`.
+We aren't claiming that this is simple, but we are claiming that it is
+possible.
+
+It's worth noting that while at first glance this may look like a
+typical use of interface types, `Node` and `Edge` are non-interface
+types with specific methods.
+In order to use `graph.Graph`, the type arguments used for `Node` and
+`Edge` have to define methods that follow a certain pattern, but they
+don't have to actually use interface types to do so.
+In particular, the methods do not return interface types.
+
+For example, consider these type definitions in some other package:
+
+```
+// Vertex is a node in a graph.
+type Vertex struct { ... }
+
+// Edges returns the edges connected to v.
+func (v *Vertex) Edges() []*FromTo { ... }
+
+// FromTo is an edge in a graph.
+type FromTo struct { ... }
+
+// Nodes returns the nodes that ft connects.
+func (ft *FromTo) Nodes() (*Vertex, *Vertex) { ... }
+```
+
+There are no interface types here, but we can instantiate
+`graph.Graph` using the type arguments `*Vertex` and `*FromTo`.
+
+```
+var g = graph.New[*Vertex, *FromTo]([]*Vertex{ ... })
+```
+
+`*Vertex` and `*FromTo` are not interface types, but when used
+together they define methods that implement the constraints of
+`graph.Graph`.
+Note that we couldn't pass plain `Vertex` or `FromTo` to `graph.New`,
+since `Vertex` and `FromTo` do not implement the constraints.
+The `Edges` and `Nodes` methods are defined on the pointer types
+`*Vertex` and `*FromTo`; the types `Vertex` and `FromTo` do not have
+any methods.
+
+When we use a generic interface type as a constraint, we first
+instantiate the type with the type argument(s) supplied in the type
+parameter list, and then compare the corresponding type argument
+against the instantiated constraint.
+In this example, the `Node` type argument to `graph.New` has a
+constraint `NodeConstraint[Edge]`.
+When we call `graph.New` with a `Node` type argument of `*Vertex` and
+an `Edge` type argument of `*FromTo`, in order to check the constraint
+on `Node` the compiler instantiates `NodeConstraint` with the type
+argument `*FromTo`.
+That produces an instantiated constraint, in this case a requirement
+that `Node` have a method `Edges() []*FromTo`, and the compiler
+verifies that `*Vertex` satisfies that constraint.
+
+Although `Node` and `Edge` do not have to be instantiated with
+interface types, it is also OK to use interface types if you like.
+
+```
+type NodeInterface interface { Edges() []EdgeInterface }
+type EdgeInterface interface { Nodes() (NodeInterface, NodeInterface) }
+```
+
+We could instantiate `graph.Graph` with the types `NodeInterface` and
+`EdgeInterface`, since they implement the type constraints.
+There isn't much reason to instantiate a type this way, but it is
+permitted.
+
+This ability for type parameters to refer to other type parameters
+illustrates an important point: it should be a requirement for any
+attempt to add generics to Go that it be possible to instantiate
+generic code with multiple type arguments that refer to each other in
+ways that the compiler can check.
+
+### Type inference
+
+In many cases we can use type inference to avoid having to explicitly
+write out some or all of the type arguments.
+We can use _function argument type inference_ for a function call to
+deduce type arguments from the types of the non-type arguments.
+We can use _constraint type inference_ to deduce unknown type arguments
+from known type arguments.
+
+In the examples above, when instantiating a generic function or type,
+we always specified type arguments for all the type parameters.
+We also permit specifying just some of the type arguments, or omitting
+the type arguments entirely, when the missing type arguments can be
+inferred.
+When only some type arguments are passed, they are the arguments for
+the first type parameters in the list.
+
+For example, a function like this:
+
+```
+func Map[F, T any](s []F, f func(F) T) []T { ... }
+```
+
+can be called in these ways.  (We'll explain below how type inference
+works in detail; this example is to show how an incomplete list of
+type arguments is handled.)
+
+```
+	var s []int
+	f := func(i int) int64 { return int64(i) }
+	var r []int64
+	// Specify both type arguments explicitly.
+	r = Map[int, int64](s, f)
+	// Specify just the first type argument, for F,
+	// and let T be inferred.
+	r = Map[int](s, f)
+	// Don't specify any type arguments, and let both be inferred.
+	r = Map(s, f)
+```
+
+If a generic function or type is used without specifying all the type
+arguments, it is an error if any of the unspecified type arguments
+cannot be inferred.
+
+(Note: type inference is a convenience feature.
+Although we think it is an important feature, it does not add any
+functionality to the design, only convenience in using it.
+It would be possible to omit it from the initial implementation, and
+see whether it seems to be needed.
+That said, this feature doesn't require additional syntax, and
+produces more readable code.)
+
+#### Type unification
+
+Type inference is based on _type unification_.
+Type unification applies to two types, either or both of which may be
+or contain type parameters.
+
+Type unification works by comparing the structure of the types.
+Their structure disregarding type parameters must be identical, and
+types other than type parameters must be equivalent.
+A type parameter in one type may match any complete subtype in the
+other type.
+If the structure differs, or types other than type parameters are not
+equivalent, then type unification fails.
+A successful type unification provides a list of associations of type
+parameters with other types (which may themselves be or contain type
+parameters).
+
+For type unification, two types that don't contain any type parameters
+are equivalent if they are
+[identical](https://golang.org/ref/spec#Type_identity), or if they are
+channel types that are identical ignoring channel direction, or if
+their underlying types are equivalent.
+It's OK to permit types to not be identical during type inference,
+because we will still check the constraints if inference succeeds, and
+we will still check that the function arguments are assignable to the
+inferred types.
+
+For example, if `T1` and `T2` are type parameters, `[]map[int]bool`
+can be unified with any of the following:
+  * `[]map[int]bool`
+  * `T1` (`T1` matches `[]map[int]bool`)
+  * `[]T1` (`T1` matches `map[int]bool`)
+  * `[]map[T1]T2` (`T1` matches `int`, `T2` matches `bool`)
+
+(This is not an exclusive list, there are other possible successful
+unifications.)
+
+On the other hand, `[]map[int]bool` cannot be unified with any of
+  * `int`
+  * `struct{}`
+  * `[]struct{}`
+  * `[]map[T1]string`
+
+(This list is of course also not exclusive; there are an infinite
+number of types that cannot be successfully unified.)
+
+In general we can also have type parameters on both sides, so in some
+cases we might associate `T1` with, for example, `T2`, or `[]T2`.
+
+#### Function argument type inference
+
+Function argument type inference is used with a function call to infer
+type arguments from non-type arguments.
+Function argument type inference is not used when a type is
+instantiated, and it is not used when a function is instantiated but
+not called.
+
+To see how it works, let's go back to [the example](#Type-parameters)
+of a call to the simple `Print` function:
+
+```
+	Print[int]([]int{1, 2, 3})
+```
+
+The type argument `int` in this function call can be inferred from the
+type of the non-type argument.
+
+The only type arguments that can be inferred are those that are used
+for the types of the function's (non-type) input parameters.
+If there are some type parameters that are used only for the
+function's result parameter types, or only in the body of the
+function, then those type arguments cannot be inferred using function
+argument type inference.
+
+To infer function type arguments, we unify the types of the function
+call arguments with the types of the function's non-type parameters.
+On the caller side we have the list of types of the actual (non-type)
+arguments, which for the `Print` example is simply `[]int`.
+On the function side is the list of the types of the function's
+non-type parameters, which for `Print` is `[]T`.
+In the lists, we discard respective arguments for which the function
+side does not use a type parameter.
+We must then apply type unification to the remaining argument types.
+
+Function argument type inference is a two-pass algorithm.
+In the first pass, we ignore untyped constants on the caller side and
+their corresponding types in the function definition.
+We use two passes so that in some cases later arguments can determine
+the type of an untyped constant.
+
+We unify corresponding types in the lists.
+This will give us an association of type parameters on the function
+side to types on the caller side.
+If the same type parameter appears more than once on the function
+side, it will match multiple argument types on the caller side.
+If those caller types are not equivalent, we report an error.
+
+After the first pass, we check any untyped constants on the caller
+side.
+If there are no untyped constants, or if the type parameters in the
+corresponding function types have matched other input types, then
+type unification is complete.
+
+Otherwise, for the second pass, for any untyped constants whose
+corresponding function types are not yet set, we determine the default
+type of the untyped constant in [the usual
+way](https://golang.org/ref/spec#Constants).
+Then we unify the remaining types again, this time with no untyped
+constants.
+
+In this example
+
+```
+	s1 := []int{1, 2, 3}
+	Print(s1)
+```
+
+we compare `[]int` with `[]T`, match `T` with `int`, and we are done.
+The single type parameter `T` is `int`, so we infer that the call to
+`Print` is really a call to `Print[int]`.
+
+For a more complex example, consider
+
+```
+// Map calls the function f on every element of the slice s,
+// returning a new slice of the results.
+func Map[F, T any](s []F, f func(F) T) []T {
+	r := make([]T, len(s))
+	for i, v := range s {
+		r[i] = f(v)
+	}
+	return r
+}
+```
+
+The two type parameters `F` and `T` are both used for input
+parameters, so function argument type inference is possible.
+In the call
+
+```
+	strs := Map([]int{1, 2, 3}, strconv.Itoa)
+```
+
+we unify `[]int` with `[]F`, matching `F` with `int`.
+We unify the type of `strconv.Itoa`, which is `func(int) string`,
+with `func(F) T`, matching `F` with `int` and `T` with `string`.
+The type parameter `F` is matched twice, both times with `int`.
+Unification succeeds, so the call written as `Map` is a call of
+`Map[int, string]`.
+
+To see the untyped constant rule in effect, consider:
+
+```
+// NewPair returns a pair of values of the same type.
+func NewPair[F any](f1, f2 F) *Pair[F] { ... }
+```
+
+In the call `NewPair(1, 2)` both arguments are untyped constants, so
+both are ignored in the first pass.
+There is nothing to unify.
+We still have two untyped constants after the first pass.
+Both are set to their default type, `int`.
+The second run of the type unification pass unifies `F` with
+`int`, so the final call is `NewPair[int](1, 2)`.
+
+In the call `NewPair(1, int64(2))` the first argument is an untyped
+constant, so we ignore it in the first pass.
+We then unify `int64` with `F`.
+At this point the type parameter corresponding to the untyped constant
+is fully determined, so the final call is `NewPair[int64](1,
+int64(2))`.
+
+In the call `NewPair(1, 2.5)` both arguments are untyped constants,
+so we move on the second pass.
+This time we set the first constant to `int` and the second to
+`float64`.
+We then try to unify `F` with both `int` and `float64`, so unification
+fails, and we report a compilation error.
+
+As mentioned earlier, function argument type inference is done without
+regard to constraints.
+First we use function argument type inference to determine type
+arguments to use for the function, and then, if that succeeds, we
+check whether those type arguments implement the constraints (if
+any).
+
+Note that after successful function argument type inference, the
+compiler must still check that the arguments can be assigned to the
+parameters, as for any function call.
+
+#### Constraint type inference
+
+Constraint type inference permits inferring a type argument from
+another type argument, based on type parameter constraints.
+Constraint type inference is useful when a function wants to have a
+type name for an element of some other type parameter, or when a
+function wants to apply a constraint to a type that is based on some
+other type parameter.
+
+Constraint type inference can only infer types if some type parameter
+has a constraint that has a type list with exactly one type in it.
+We call such a constraint a _structural constraint_, as the type list
+describes the structure of the type parameter.
+A structural constraint may also have methods in addition to the type
+list, but the methods are ignored by constraint type inference.
+For constraint type inference to be useful, the constraint type will
+normally refer to one or more type parameters.
+
+Constraint type inference is applied after function argument type
+inference.
+It is only tried if there is at least one type parameter whose type
+argument is not yet known.
+
+While the algorithm we describe here may seem complex, for typical
+concrete examples it is straightforward to see what constraint type
+inference will deduce.
+The description of the algorithm is followed by a couple of examples.
+
+We start by creating a mapping from type parameters to type arguments.
+We initialize the mapping with all type parameters whose type
+arguments are already known, if any.
+
+For each type parameter with a structural constraint, we unify the
+type parameter with the single type in the constraint's type list.
+This will have the effect of associating the type parameter with its
+constraint.
+We add the result into the mapping we are maintaining.
+If unification finds any associations of type parameters, we add those
+to the mapping as well.
+When we find multiple associations of any one type parameter, we unify
+each such association to produce a single mapping entry.
+If a type parameter is associated directly with another type
+parameter, meaning that they must both be matched with the same type,
+we unify the associations of each parameter together.
+If any of these various unifications fail, then constraint type
+inference fails.
+
+After merging all type parameters with structural constraints, we have
+a mapping of various type parameters to types (which may be or contain
+other type parameters).
+We continue by looking for a type parameter `T` that is mapped to a
+fully known type argument `A`, one that does not contain any type
+parameters.
+Anywhere that `T` appears in a type argument in the mapping, we
+replace `T` with `A`.
+We repeat this process until we have replaced every type parameter.
+
+##### Element constraint example
+
+For an example of where constraint type inference is useful, let's
+consider a function that takes a defined type that is a slice of
+numbers, and returns an instance of that same defined type in which
+each number is doubled.
+
+Using type lists, it's easy to write a function similar to this if we
+ignore the [defined
+type](https://golang.org/ref/spec#Type_definitions) requirement.
+
+```
+// Double returns a new slice that contains all the elements of s, doubled.
+func Double[E constraints.Number](s []E) []E {
+	r := make([]E, len(s))
+	for i, v := range s {
+		r[i] = v + v
+	}
+	return r
+}
+```
+
+However, with that definition, if we call the function with a defined
+slice type, the result will not be that defined type.
+
+```
+// MySlice is a slice of ints.
+type MySlice []int
+
+// The type of V1 will be []int, not MySlice.
+// Here we are using function argument type inference,
+// but not constraint type inference.
+var V1 = Double(MySlice{1})
+```
+
+We can do what we want by introducing a new type parameter.
+
+```
+// SC constraints a type to be a slice of some type E.
+type SC[E any] interface {
+	type []E
+}
+
+// DoubleDefined returns a new slice that contains the elements of s,
+// doubled, and also has the same type as s.
+func DoubleDefined[S SC[E], E constraints.Number](s S) S {
+	// Note that here we pass S to make, where above we passed []E.
+	r := make(S, len(s))
+	for i, v := range s {
+		r[i] = v + v
+	}
+	return r
+}
+```
+
+Now if we use explicit type arguments, we can get the right type.
+
+```
+// The type of V2 will be MySlice.
+var V2 = DoubleDefined[MySlice, int](MySlice{1})
+```
+
+Function argument type inference by itself is not enough to infer the
+type arguments here, because the type parameter E is not used for any
+input parameter.
+But a combination of function argument type inference and constraint
+type inference works.
+
+```
+// The type of V3 will be MySlice.
+var V3 = DoubleDefined(MySlice{1})
+```
+
+First we apply function argument type inference.
+We see that the type of the argument is `MySlice`.
+Function argument type inference matches the type parameter `S` with
+`MySlice`.
+
+We then move on to constraint type inference.
+We know one type argument, `S`.
+We see that the type argument `S` has a structural type constraint.
+
+We create a mapping of known type arguments:
+
+```
+{S -> MySlice}
+```
+
+We then unify each type parameter with a structural constraint with
+the single type listed by that constraint.
+In this case the structural constraint is `SC[E]` which has the single
+type `[]E`, so we unify `S` with `[]E`.
+Since we already have a mapping for `S`, we then unify `[]E` with
+`MySlice`.
+As `MySlice` is defined as `[]int`, that associates `E` with `int`.
+We now have:
+
+```
+{S -> MySlice, E -> int}
+```
+
+We then substitute `E` with `int`, which changes nothing, and we are
+done.
+The type arguments for this call to `DoubleDefined` are `[MySlice,
+int]`.
+
+This example shows how we can use constraint type inference to set a
+type name for an element of some other type parameter.
+In this case we can name the element type of `S` as `E`, and we can
+then apply further constraints to `E`, in this case requiring that it
+be a number.
+
+##### Pointer method example
+
+Consider this example of a function that expects a type `T` that has a
+`Set(string)` method that initializes a value based on a string.
+
+```
+// Setter is a type constraint that requires that the type
+// implement a Set method that sets the value from a string.
+type Setter interface {
+	Set(string)
+}
+
+// FromStrings takes a slice of strings and returns a slice of T,
+// calling the Set method to set each returned value.
+//
+// Note that because T is only used for a result parameter,
+// function argument type inference does not work when calling
+// this function.
+func FromStrings[T Setter](s []string) []T {
+	result := make([]T, len(s))
+	for i, v := range s {
+		result[i].Set(v)
+	}
+	return result
+}
+```
+
+Now let's see some calling code (this example is invalid).
+
+```
+// Settable is an integer type that can be set from a string.
+type Settable int
+
+// Set sets the value of *p from a string.
+func (p *Settable) Set(s string) {
+	i, _ := strconv.Atoi(s) // real code should not ignore the error
+	*p = Settable(i)
+}
+
+func F() {
+	// INVALID
+	nums := FromStrings[Settable]([]string{"1", "2"})
+	// Here we want nums to be []Settable{1, 2}.
+	...
+}
+```
+
+The goal is to use `FromStrings` to get a slice of type `[]Settable`.
+Unfortunately, this example is not valid and will not compile.
+
+The problem is that `FromStrings` requires a type that has a
+`Set(string)` method.
+The function `F` is trying to instantiate `FromStrings` with
+`Settable`, but `Settable` does not have a `Set` method.
+The type that has a `Set` method is `*Settable`.
+
+So let's rewrite `F` to use `*Settable` instead.
+
+```
+func F() {
+	// Compiles but does not work as desired.
+	// This will panic at run time when calling the Set method.
+	nums := FromStrings[*Settable]([]string{"1", "2"})
+	...
+}
+```
+
+This compiles but unfortunately it will panic at run time.
+The problem is that `FromStrings` creates a slice of type `[]T`.
+When instantiated with `*Settable`, that means a slice of type
+`[]*Settable`.
+When `FromStrings` calls `result[i].Set(v)`, that invokes the `Set`
+method on the pointer stored in `result[i]`.
+That pointer is `nil`.
+The `Settable.Set` method will be invoked with a `nil` receiver, and
+will raise a panic due to a `nil` dereference error.
+
+The pointer type `*Settable` implements the constraint, but the code
+really wants to use the non-pointer type`Settable`.
+What we need is a way to write `FromStrings` such that it can take the
+type `Settable` as an argument but invoke a pointer method.
+To repeat, we can't use `Settable` because it doesn't have a `Set`
+method, and we can't use `*Settable` because then we can't create a
+slice of type `Settable`.
+
+What we can do is pass both types.
+
+```
+// Setter2 is a type constraint that requires that the type
+// implement a Set method that sets the value from a string,
+// and also requires that the type be a pointer to its type parameter.
+type Setter2[B any] interface {
+	Set(string)
+	type *B
+}
+
+// FromStrings2 takes a slice of strings and returns a slice of T,
+// calling the Set method to set each returned value.
+//
+// We use two different type parameters so that we can return
+// a slice of type T but call methods on *T aka PT.
+// The Setter2 constraint ensures that PT is a pointer to T.
+func FromStrings2[T any, PT Setter2[T]](s []string) []T {
+	result := make([]T, len(s))
+	for i, v := range s {
+		// The type of &result[i] is *T which is in the type list
+		// of Setter2, so we can convert it to PT.
+		p := PT(&result[i])
+		// PT has a Set method.
+		p.Set(v)
+	}
+	return result
+}
+```
+
+We can then call `FromStrings2` like this:
+
+```
+func F2() {
+	// FromStrings2 takes two type parameters.
+	// The second parameter must be a pointer to the first.
+	// Settable is as above.
+	nums := FromStrings2[Settable, *Settable]([]string{"1", "2"})
+	// Now nums is []Settable{1, 2}.
+	...
+}
+```
+
+This approach works as expected, but it is awkward to have to repeat
+`Settable` in the type arguments.
+Fortunately, constraint type inference makes it less awkward.
+Using constraint type inference we can write
+
+```
+func F3() {
+	// Here we just pass one type argument.
+	nums := FromStrings2[Settable]([]string{"1", "2"})
+	// Now nums is []Settable{1, 2}.
+	...
+}
+```
+
+There is no way to avoid passing the type argument `Settable`.
+But given that type argument, constraint type inference can infer the
+type argument `*Settable` for the type parameter `PT`.
+
+As before, we create a mapping of known type arguments:
+
+```
+{T -> Settable}
+```
+
+We then unify each type parameter with a structural constraint.
+In this case, we unify `PT` with the single type of `Setter2[T]`,
+which is `*T`.
+The mapping is now
+
+```
+{T -> Settable, PT -> *T}
+```
+
+We then replace `T` with `Settable` throughout, giving us:
+
+```
+{T -> Settable, PT -> *Settable}
+```
+
+After this nothing changes, and we are done.
+Both type arguments are known.
+
+This example shows how we can use constraint type inference to apply a
+constraint to a type that is based on some other type parameter.
+In this case we are saying that `PT`, which is `*T`, must have a `Set`
+method.
+We can do this without requiring the caller to explicitly mention
+`*T`.
+
+##### Constraints apply even after constraint type inference
+
+Even when constraint type inference is used to infer type arguments
+based on constraints, we must still check the constraints after the
+type arguments are determined.
+
+In the `FromStrings2` example above, we were able to deduce the type
+argument for `PT` based on the `Setter2` constraint.
+But in doing so we only looked at the type list, we didn't look at the
+methods.
+We still have to verify that the method is there, satisfying the
+constraint, even if constraint type inference succeeds.
+
+For example, consider this invalid code:
+
+```
+// Unsettable is a type that does not have a Set method.
+type Unsettable int
+
+func F4() {
+	// This call is INVALID.
+	nums := FromString2[Unsettable]([]string{"1", "2"})
+	...
+}
+```
+
+When this call is made, we will apply constraint type inference just
+as before.
+It will succeed, just as before, and infer that the type arguments are
+`[Unsettable, *Unsettable]`.
+Only after constraint type inference is complete will we check whether
+`*Unsettable` implements the constraint `Setter2[Unsettable]`.
+Since `*Unsettable` does not have a `Set` method, constraint checking
+will fail, and this code will not compile.
+
+### Using types that refer to themselves in constraints
+
+It can be useful for a generic function to require a type argument
+with a method whose argument is the type itself.
+For example, this arises naturally in comparison methods.
+(Note that we are talking about methods here, not operators.)
+Suppose we want to write an `Index` method that uses an `Equal` method
+to check whether it has found the desired value.
+We would like to write that like this:
+
+```
+// Index returns the index of e in s, or -1 if not found.
+func Index[T Equaler](s []T, e T) int {
+	for i, v := range s {
+		if e.Equal(v) {
+			return i
+		}
+	}
+	return -1
+}
+```
+
+In order to write the `Equaler` constraint, we have to write a
+constraint that can refer to the type argument being passed in.
+The easiest way to do this is to take advantage of the fact that a
+constraint does not have to be a defined type, it can simply be an
+interface type literal.
+This interface type literal can then refer to the type parameter.
+
+```
+// Index returns the index of e in s, or -1 if not found.
+func Index[T interface { Equal(T) bool }](s []T, e T) int {
+	// same as above
+}
+```
+
+This version of `Index` would be used with a type like `equalInt`
+defined here:
+
+```
+// equalInt is a version of int that implements Equaler.
+type equalInt int
+
+// The Equal method lets equalInt implement the Equaler constraint.
+func (a equalInt) Equal(b equalInt) bool { return a == b }
+
+// indexEqualInts returns the index of e in s, or -1 if not found.
+func indexEqualInt(s []equalInt, e equalInt) int {
+	// The type argument equalInt is shown here for clarity.
+	// Function argument type inference would permit omitting it.
+	return Index[equalInt](s, e)
+}
+```
+
+In this example, when we pass `equalInt` to `Index`, we check whether
+`equalInt` implements the constraint `interface { Equal(T) bool }`.
+The constraint has a type parameter, so we replace the type parameter
+with the type argument, which is `equalInt` itself.
+That gives us `interface { Equal(equalInt) bool }`.
+The `equalInt` type has an `Equal` method with that signature, so all
+is well, and the compilation succeeds.
+
+### Values of type parameters are not boxed
+
+In the current implementations of Go, interface values always hold
+pointers.
+Putting a non-pointer value in an interface variable causes the value
+to be _boxed_.
+That means that the actual value is stored somewhere else, on the heap
+or stack, and the interface value holds a pointer to that location.
+
+In this design, values of generic types are not boxed.
+For example, let's look back at our earlier example of
+`FromStrings2`.
+When it is instantiated with type `Settable`, it returns a value of
+type `[]Settable`.
+For example, we can write
+
+```
+// Settable is an integer type that can be set from a string.
+type Settable int
+
+// Set sets the value of *p from a string.
+func (p *Settable) Set(s string) {
+	// same as above
+}
+
+func F() {
+	// The type of nums is []Settable.
+	nums := FromStrings2[Settable]([]string{"1", "2"})
+	// Settable can be converted directly to int.
+	// This will set first to 1.
+	first := int(nums[0])
+	...
+}
+```
+
+When we call `FromStrings2` instantiated with the type `Settable` we
+get back a `[]Settable`.
+The elements of that slice will be `Settable` values, which is to say,
+they will be integers.
+They will not be boxed, even though they were created and set by a
+generic function.
+
+Similarly, when a generic type is instantiated it will have the
+expected types as components.
+
+```
+type Pair[F1, F2 any] struct {
+	first  F1
+	second F2
+}
+```
+
+When this is instantiated, the fields will not be boxed, and no
+unexpected memory allocations will occur.
+The type `Pair[int, string]` is convertible to `struct { first int;
+second string }`.
+
+### More on type lists
+
+Let's return now to type lists to cover some less important details
+that are still worth noting.
+These are not additional rules or concepts, but are consequences of
+how type lists work.
+
+#### Both type lists and methods in constraints
+
+As seen earlier for `Setter2`, a constraint may use both type lists
+and methods.
+
+```
+// StringableSignedInteger is a type constraint that matches any
+// type that is both 1) defined as a signed integer type;
+// 2) has a String method.
+type StringableSignedInteger interface {
+	type int, int8, int16, int32, int64
+	String() string
+}
+```
+
+This constraint permits any type whose underlying type is one of the
+listed types, provided it also has a `String() string` method.
+It's worth noting that although the `StringableSignedInteger`
+constraint explicitly lists `int`, the type `int` will not itself be
+permitted as a type argument, since `int` does not have a `String`
+method.
+An example of a type argument that would be permitted is `MyInt`,
+defined as:
+
+```
+// MyInt is a stringable int.
+type MyInt int
+
+// The String method returns a string representation of mi.
+func (mi MyInt) String() string {
+	return fmt.Sprintf("MyInt(%d)", mi)
+}
+```
+
+#### Types with methods in type lists
+
+Using a type list permits a generic function to use an operation that
+is permitted by all the types in the type list.
+However, that does not apply to methods.
+Even if every type in the type list supports the same method with the
+same signature, the generic function may not call that method.
+It may only call methods that are explicitly listed in the constraint,
+as explained in the previous section.
+
+Here is an example of types with the same method.
+This example is invalid.
+Even though both `MyInt` and `MyFloat` have a `String` method, the
+`ToString` function is not permitted to call that method.
+
+```
+// MyInt has a String method.
+type MyInt int
+
+func (i MyInt) String() string {
+	return strconv.Itoa(int(i))
+}
+
+// MyFloat also has a String method.
+type MyFloat float64
+
+func (f MyFloat) String() string {
+	return strconv.FormatFloat(float64(f), 'g', -1, 64)
+}
+
+// MyIntOrFloat is a type constraint that accepts MyInt or MyFloat.
+type MyIntOrFloat interface {
+	type MyInt, MyFloat
+}
+
+// ToString converts a value to a string.
+// This function is INVALID.
+func ToString[T MyIntOrFloat](v T) string {
+	return v.String() // INVALID
+}
+```
+
+To permit the `String` method to be called, it must be explicitly
+listed in the constraint.
+
+```
+// MyIntOrFloatStringer accepts MyInt or MyFloat, and defines a String
+// method. Note that both MyInt and MyFloat have a String method.
+// If either did not have a String method, they would not satisfy the
+// constraint even though the type list lists them. To satisfy a
+// constraint a type must both match the type list (if any) and
+// implement all the methods (if any).
+type MyIntOrFloatStringer interface {
+	type MyInt, MyFloat
+	String() string
+}
+
+// ToString2 convers a value to a string.
+func ToString2[T MyIntOrFloatStringer](v T) string {
+	return v.String()
+}
+```
+
+The reason for this rule is to simplify complex cases involving
+embedded type parameters in which it may not be immediately clear
+whether the type has a particular method or not.
+
+#### Composite types in constraints
+
+A type in a constraint may be a type literal.
+
+```
+type byteseq interface {
+	type string, []byte
+}
+```
+
+The usual rules apply: the type argument for this constraint may be
+`string` or `[]byte` or a type defined as one of those types; a
+generic function with this constraint may use any operation permitted
+by both `string` and `[]byte`.
+
+The `byteseq` constraint permits writing generic functions that work
+for either `string` or `[]byte` types.
+
+```
+// Join concatenates the elements of its first argument to create a
+// single value. sep is placed between elements in the result.
+// Join works for string and []byte types.
+func Join[T byteseq](a []T, sep T) (ret T) {
+	if len(a) == 0 {
+		// Use the result parameter as a zero value;
+		// see discussion of zero value in the Issues section.
+		return ret
+	}
+	if len(a) == 1 {
+		// We know that a[0] is either a string or a []byte.
+		// We can append either a string or a []byte to a []byte,
+		// producing a []byte. We can convert that []byte to
+		// either a []byte (a no-op conversion) or a string.
+		return T(append([]byte(nil), a[0]...))
+	}
+	// We can call len on sep because we can call len
+	// on both string and []byte.
+	n := len(sep) * (len(a) - 1)
+	for _, v := range a {
+		// Another case where we call len on string or []byte.
+		n += len(v)
+	}
+
+	b := make([]byte, n)
+	// We can call copy to a []byte with an argument of
+	// either string or []byte.
+	bp := copy(b, a[0])
+	for _, s := range a[1:] {
+		bp += copy(b[bp:], sep)
+		bp += copy(b[bp:], s)
+	}
+	// As above, we can convert b to either []byte or string.
+	return T(b)
+}
+```
+
+For composite types (string, pointer, array, slice, struct, function,
+map, channel) we impose an additional restriction: an operation may
+only be used if the operator accepts identical input types (if any)
+and produces identical result types for all of the types listed in the
+type list.
+To be clear, this additional restriction is only imposed when a
+composite type appears in a type list.
+It does not apply when a composite type is formed from a type
+parameter outside of a type list, as in `var v []T` for some type
+parameter `T`.
+
+```
+// structField is a type constraint with a list of structs that all
+// have a field named x.
+type structField interface {
+	type struct { a int; x int },
+		struct { b int; x float64 },
+		struct { c int; x uint64 }
+}
+
+// This function is INVALID.
+func IncrementX[T structField](p *T) {
+	v := p.x // INVALID: type of p.x is not the same for all types in list
+	v++
+	p.x = v
+}
+
+// sliceOrMap is a type constraint for a slice or a map.
+type sliceOrMap interface {
+	type []int, map[int]int
+}
+
+// Entry returns the i'th entry in a slice or the value of a map
+// at key i. This is valid as the result of the operator is always int.
+func Entry[T sliceOrMap](c T, i int) int {
+	// This is either a slice index operation or a map key lookup.
+	// Either way, the index and result types are type int.
+	return c[i]
+}
+
+// sliceOrFloatMap is a type constraint for a slice or a map.
+type sliceOrFloatMap interface {
+	type []int, map[float64]int
+}
+
+// This function is INVALID.
+// In this example the input type of the index operation is either
+// int (for a slice) or float64 (for a map), so the operation is
+// not permitted.
+func FloatEntry[T sliceOrFloatMap](c T) int {
+	return c[1.0] // INVALID: input type is either int or float64.
+}
+```
+
+Imposing this restriction makes it easier to reason about the type of
+some operation in a generic function.
+It avoids introducing the notion of a value whose type is the union of
+a set of types found by applying some operation to each element of a
+type list.
+
+(Note: with more understanding of how people want to write code, it
+may be possible to relax this restriction in the future.)
+
+#### Type parameters in type lists
+
+A type literal in a constraint can refer to type parameters of the
+constraint.
+In this example, the generic function `Map` takes two type parameters.
+The first type parameter is required to have an underlying type that
+is a slice of the second type parameter.
+There are no constraints on the second slice parameter.
+
+```
+// SliceConstraint is a type constraint that matches a slice of
+// the type parameter.
+type SliceConstraint[T any] interface {
+	type []T
+}
+
+// Map takes a slice of some element type and a transformation function,
+// and returns a slice of the function applied to each element.
+// Map returns a slice that is the same type as its slice argument,
+// even if that is a defined type.
+func Map[S SliceConstraint[E], E any](s S, f func(E) E) S {
+	r := make(S, len(s))
+	for i, v := range s {
+		r[i] = f(v)
+	}
+	return r
+}
+
+// MySlice is a simple defined type.
+type MySlice []int
+
+// DoubleMySlice takes a value of type MySlice and returns a new
+// MySlice value with each element doubled in value.
+func DoubleMySlice(s MySlice) MySlice {
+	// The type arguments listed explicitly here could be inferred.
+	v := Map[MySlice, int](s, func(e int) int { return 2 * e })
+	// Here v has type MySlice, not type []int.
+	return v
+}
+```
+
+We showed other examples of this earlier in the discussion of
+[constraint type inference](#Constraint-type-inference).
+
+#### Type conversions
+
+In a function with two type parameters `From` and `To`, a value of
+type `From` may be converted to a value of type `To` if all the
+types accepted by `From`'s constraint can be converted to all the
+types accepted by `To`'s constraint.
+If either type parameter does not have a type list, type conversions
+are not permitted.
+
+This is a consequence of the general rule that a generic function may
+use any operation that is permitted by all types listed in the type
+list.
+
+For example:
+
+```
+type integer interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr
+}
+
+func Convert[To, From integer](from From) To {
+	to := To(from)
+	if From(to) != from {
+		panic("conversion out of range")
+	}
+	return to
+}
+```
+
+The type conversions in `Convert` are permitted because Go permits
+every integer type to be converted to every other integer type.
+
+#### Untyped constants
+
+Some functions use untyped constants.
+An untyped constant is permitted with a value of a type parameter if
+it is permitted with every type accepted by the type parameter's
+constraint.
+
+As with type conversions, this is a consequence of the general rule
+that a generic function may use any operation that is permitted by all
+types listed in the type list.
+
+```
+type integer interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr
+}
+
+func Add10[T integer](s []T) {
+	for i, v := range s {
+		s[i] = v + 10 // OK: 10 can convert to any integer type
+	}
+}
+
+// This function is INVALID.
+func Add1024[T integer](s []T) {
+	for i, v := range s {
+		s[i] = v + 1024 // INVALID: 1024 not permitted by int8/uint8
+	}
+}
+```
+
+#### Type lists in embedded constraints
+
+When a constraint embeds another constraint, the type list of the
+final constraint is the intersection of all the type lists involved.
+If there are multiple embedded types, intersection preserves the
+property that any  type argument must satisfy the requirements of all
+embedded types.
+
+```
+// Addable is types that support the + operator.
+type Addable interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr,
+		float32, float64, complex64, complex128,
+		string
+}
+
+// Byteseq is a byte sequence: either string or []byte.
+type Byteseq interface {
+	type string, []byte
+}
+
+// AddableByteseq is a byte sequence that supports +.
+// This is every type is that is both Addable and Byteseq.
+// In other words, just the type string.
+type AddableByteseq interface {
+	Addable
+	Byteseq
+}
+```
+
+#### General notes on type lists
+
+It may seem awkward to explicitly list types in a constraint, but it
+is clear both as to which type arguments are permitted at the call
+site, and which operations are permitted by the generic function.
+
+If the language later changes to support operator methods (there are
+no such plans at present), then constraints will handle them as they
+do any other kind of method.
+
+There will always be a limited number of predeclared types, and a
+limited number of operators that those types support.
+Future language changes will not fundamentally change those facts, so
+this approach will continue to be useful.
+
+This approach does not attempt to handle every possible operator.
+The expectation is that composite types will normally be handled using
+composite types in generic function and type declarations, rather than
+putting composite types in a type list.
+For example, we expect functions that want to index into a slice to be
+parameterized on the slice element type `T`, and to use parameters or
+variables of type `[]T`.
+
+As shown in the `DoubleMySlice` example above, this approach makes it
+awkward to declare generic functions that accept and return a
+composite type and want to return the same result type as their
+argument type.
+Defined composite types are not common, but they do arise.
+This awkwardness is a weakness of this approach.
+Constraint type inference can help at the call site.
+
+### Reflection
+
+We do not propose to change the reflect package in any way.
+When a type or function is instantiated, all of the type parameters
+will become ordinary non-generic types.
+The `String` method of a `reflect.Type` value of an instantiated type
+will return the name with the type arguments in square brackets.
+For example, `List[int]`.
+
+It's impossible for non-generic code to refer to generic code without
+instantiating it, so there is no reflection information for
+uninstantiated generic types or functions.
+
+### Implementation
+
+Russ Cox [famously observed](https://research.swtch.com/generic) that
+generics require choosing among slow programmers, slow compilers, or
+slow execution times.
+
+We believe that this design permits different implementation choices.
+Code may be compiled separately for each set of type arguments, or it
+may be compiled as though each type argument is handled similarly to
+an interface type with method calls, or there may be some combination
+of the two.
+
+In other words, this design permits people to stop choosing slow
+programmers, and permits the implementation to decide between slow
+compilers (compile each set of type arguments separately) or slow
+execution times (use method calls for each operation on a value of a
+type argument).
+
+### Summary
+
+While this document is long and detailed, the actual design reduces to
+a few major points.
+
+* Functions and types can have type parameters, which are defined
+  using constraints, which are interface types.
+* Constraints describe the methods required and the types permitted
+  for a type argument.
+* Constraints describe the methods and operations permitted for a type
+  parameter.
+* Type inference will often permit omitting type arguments when
+  calling functions with type parameters.
+
+This design is completely backward compatible.
+
+We believe that this design addresses people's needs for generic
+programming in Go, without making the language any more complex than
+necessary.
+
+We can't truly know the impact on the language without years of
+experience with this design.
+That said, here are some speculations.
+
+#### Complexity
+
+One of the great aspects of Go is its simplicity.
+Clearly this design makes the language more complex.
+
+We believe that the increased complexity is small for people reading
+well written generic code, rather than writing it.
+Naturally people must learn the new syntax for declaring type
+parameters.
+This new syntax, and the new support for type lists in interfaces, are
+the only new syntactic constructs in this design.
+The code within a generic function reads like ordinary Go code, as can
+be seen in the examples below.
+It is an easy shift to go from `[]int` to `[]T`.
+Type parameter constraints serve effectively as documentation,
+describing the type.
+
+We expect that most packages will not define generic types or
+functions, but many packages are likely to use generic types or
+functions defined elsewhere.
+In the common case, generic functions work exactly like non-generic
+functions: you simply call them.
+Type inference means that you do not have to write out the type
+arguments explicitly.
+The type inference rules are designed to be unsurprising: either the
+type arguments are deduced correctly, or the call fails and requires
+explicit type parameters.
+Type inference uses type equivalence, with no attempt to resolve two
+types that are similar but not equivalent, which removes significant
+complexity.
+
+Packages using generic types will have to pass explicit type
+arguments.
+The syntax for this is straightforward.
+The only change is passing arguments to types rather than only to
+functions.
+
+In general, we have tried to avoid surprises in the design.
+Only time will tell whether we succeeded.
+
+#### Pervasiveness
+
+We expect that a few new packages will be added to the standard
+library.
+A new `slices` packages will be similar to the existing bytes and
+strings packages, operating on slices of any element type.
+New `maps` and `chans` packages will provide algorithms that are
+currently duplicated for each element type.
+A `sets` package may be added.
+
+A new `constraints` package will provide standard constraints, such as
+constraints that permit all integer types or all numeric types.
+
+Packages like `container/list` and `container/ring`, and types like
+`sync.Map` and `sync/atomic.Value`, will be updated to be compile-time
+type-safe, either using new names or new versions of the packages.
+
+The `math` package will be extended to provide a set of simple
+standard algorithms for all numeric types, such as the ever popular
+`Min` and `Max` functions.
+
+We may add generic variants to the `sort` package.
+
+It is likely that new special purpose compile-time type-safe container
+types will be developed.
+
+We do not expect approaches like the C++ STL iterator types to become
+widely used.
+In Go that sort of idea is more naturally expressed using an interface
+type.
+In C++ terms, using an interface type for an iterator can be seen as
+carrying an abstraction penalty, in that run-time efficiency will be
+less than C++ approaches that in effect inline all code; we believe
+that Go programmers will continue to find that sort of penalty to be
+acceptable.
+
+As we get more container types, we may develop a standard `Iterator`
+interface.
+That may in turn lead to pressure to modify the language to add some
+mechanism for using an `Iterator` with the `range` clause.
+That is very speculative, though.
+
+#### Efficiency
+
+It is not clear what sort of efficiency people expect from generic
+code.
+
+Generic functions, rather than generic types, can probably be compiled
+using an interface-based approach.
+That will optimize compile time, in that the function is only compiled
+once, but there will be some run time cost.
+
+Generic types may most naturally be compiled multiple times for each
+set of type arguments.
+This will clearly carry a compile time cost, but there shouldn't be
+any run time cost.
+Compilers can also choose to implement generic types similarly to
+interface types, using special purpose methods to access each element
+that depends on a type parameter.
+
+Only experience will show what people expect in this area.
+
+#### Omissions
+
+We believe that this design covers the basic requirements for
+generic programming.
+However, there are a number of programming constructs that are not
+supported.
+
+* No specialization.
+  There is no way to write multiple versions of a generic function
+  that are designed to work with specific type arguments.
+* No metaprogramming.
+  There is no way to write code that is executed at compile time to
+  generate code to be executed at run time.
+* No higher level abstraction.
+  There is no way to use a function with type arguments other than to
+  call it or instantiate it.
+  There is no way to use a generic type other than to instantiate it.
+* No general type description.
+  In order to use operators in a generic function, constraints list
+  specific types, rather than describing the characteristics that a
+  type must have.
+  This is easy to understand but may be limiting at times.
+* No covariance or contravariance of function parameters.
+* No operator methods.
+  You can write a generic container that is compile-time type-safe,
+  but you can only access it with ordinary methods, not with syntax
+  like `c[k]`.
+* No currying.
+  There is no way to partially instantiate a generic function or type,
+  other than by using a helper function or a wrapper type.
+  All type arguments must be either explicitly passed or inferred at
+  instantiation time.
+* No variadic type parameters.
+  There is no support for variadic type parameters, which would permit
+  writing a single generic function that takes different numbers of
+  both type parameters and regular parameters.
+* No adaptors.
+  There is no way for a constraint to define adaptors that could be
+  used to support type arguments that do not already implement the
+  constraint, such as, for example, defining an `==` operator in terms
+  of an `Equal` method, or vice-versa.
+* No parameterization on non-type values such as constants.
+  This arises most obviously for arrays, where it might sometimes be
+  convenient to write `type Matrix[n int] [n][n]float64`.
+  It might also sometimes be useful to specify significant values for
+  a container type, such as a default value for elements.
+
+#### Issues
+
+There are some issues with this design that deserve a more detailed
+discussion.
+We think these issues are relatively minor compared to the design as a
+whole, but they still deserve a complete hearing and discussion.
+
+##### The zero value
+
+This design has no simple expression for the zero value of a type
+parameter.
+For example, consider this implementation of optional values that uses
+pointers:
+
+```
+type Optional[T any] struct {
+	p *T
+}
+
+func (o Optional[T]) Val() T {
+	if o.p != nil {
+		return *o.p
+	}
+	var zero T
+	return zero
+}
+```
+
+In the case where `o.p == nil`, we want to return the zero value of
+`T`, but we have no way to write that.
+It would be nice to be able to write `return nil`, but that wouldn't
+work if `T` is, say, `int`; in that case we would have to write
+`return 0`.
+And, of course, there is no way to write a constraint to support
+either `return nil` or `return 0`.
+
+Some approaches to this are:
+
+* Use `var zero T`, as above, which works with the existing design
+  but requires an extra statement.
+* Use `*new(T)`, which is cryptic but works with the existing
+  design.
+* For results only, name the result parameter, and use a naked
+  `return` statement to return the zero value.
+* Extend the design to permit using `nil` as the zero value of any
+  generic type (but see [issue 22729](https://golang.org/issue/22729)).
+* Extend the design to permit using `T{}`, where `T` is a type
+  parameter, to indicate the zero value of the type.
+* Change the language to permit using `_` on the right hand of an
+  assignment (including `return` or a function call) as proposed in
+  [issue 19642](https://golang.org/issue/19642).
+* Change the language to permit `return ...` to return zero values of
+  the result types, as proposed in
+  [issue 21182](https://golang.org/issue/21182).
+
+We feel that more experience with this design is needed before
+deciding what, if anything, to do here.
+
+##### Identifying the matched predeclared type
+
+The design doesn't provide any way to test the underlying type matched
+by a type argument.
+Code can test the actual type argument through the somewhat awkward
+approach of converting to an empty interface type and using a type
+assertion or a type switch.
+But that lets code test the actual type argument, which is not the
+same as the underlying type.
+
+Here is an example that shows the difference.
+
+```
+type Float interface {
+	type float32, float64
+}
+
+func NewtonSqrt[T Float](v T) T {
+	var iterations int
+	switch (interface{})(v).(type) {
+	case float32:
+		iterations = 4
+	case float64:
+		iterations = 5
+	default:
+		panic(fmt.Sprintf("unexpected type %T", v))
+	}
+	// Code omitted.
+}
+
+type MyFloat float32
+
+var G = NewtonSqrt(MyFloat(64))
+```
+
+This code will panic when initializing `G`, because the type of `v` in
+the `NewtonSqrt` function will be `MyFloat`, not `float32` or
+`float64`.
+What this function actually wants to test is not the type of `v`, but
+the type that `v` matched in the constraint.
+
+One way to handle this would be to permit type switches on the type
+`T`, with the proviso that the type `T` would always match a type
+defined in the constraint.
+This kind of type switch would only be permitted if the constraint
+lists explicit types, and only types listed in the constraint would be
+permitted as cases.
+
+##### No way to express convertibility
+
+The design has no way to express convertibility between two different
+type parameters.
+For example, there is no way to write this function:
+
+```
+// Copy copies values from src to dst, converting them as they go.
+// It returns the number of items copied, which is the minimum of
+// the lengths of dst and src.
+// This implementation is INVALID.
+func Copy[T1, T2 any](dst []T1, src []T2) int {
+	for i, x := range src {
+		if i > len(dst) {
+			return i
+		}
+		dst[i] = T1(x) // INVALID
+	}
+	return len(src)
+}
+```
+
+The conversion from type `T2` to type `T1` is invalid, as there is no
+constraint on either type that permits the conversion.
+Worse, there is no way to write such a constraint in general.
+In the particular case where both `T1` and `T2` can require some type
+list, then this function can be written as described earlier when
+discussing [type conversions using type lists](#Type-conversions).
+But, for example, there is no way to write a constraint for the case
+in which `T1` is an interface type and `T2` is a type that implements
+that interface.
+
+It's worth noting that if `T1` is an interface type then this can be
+written using a conversion to the empty interface type and a type
+assertion, but this is, of course, not compile-time type-safe.
+
+```
+// Copy copies values from src to dst, converting them as they go.
+// It returns the number of items copied, which is the minimum of
+// the lengths of dst and src.
+func Copy[T1, T2 any](dst []T1, src []T2) int {
+	for i, x := range src {
+		if i > len(dst) {
+			return i
+		}
+		dst[i] = (interface{})(x).(T1)
+	}
+	return len(src)
+}
+```
+
+##### No parameterized methods
+
+This design does not permit methods to declare type parameters that
+are specific to the method.
+The receiver may have type parameters, but the method may not add any
+type parameters.
+
+In Go, one of the main roles of methods is to permit types to
+implement interfaces.
+It is not clear whether it is reasonably possible to permit
+parameterized methods to implement interfaces.
+For example, consider this code, which uses the obvious syntax for
+parameterized methods.
+This code uses multiple packages to make the problem clearer.
+
+```
+package p1
+
+// S is a type with a parameterized method Identity.
+type S struct{}
+
+// Identity is a simple identity method that works for any type.
+func (S) Identity[T any](v T) T { return v }
+
+package p2
+
+// HasIdentity is an interface that matches any type with a
+// parameterized Identity method.
+type HasIdentity interface {
+	Identity[T any](T) T
+}
+
+package p3
+
+import "p2"
+
+// CheckIdentity checks the Identity method if it exists.
+// Note that although this function calls a parameterized method,
+// this function is not itself parameterized.
+func CheckIdentity(v interface{}) {
+	if vi, ok := v.(p2.HasIdentity); ok {
+		if got := vi.Identity[int](0); got != 0 {
+			panic(got)
+		}
+	}
+}
+
+package p4
+
+import (
+	"p1"
+	"p3"
+)
+
+// CheckSIdentity passes an S value to CheckIdentity.
+func CheckSIdentity() {
+	p3.CheckIdentity(p1.S{})
+}
+```
+
+In this example, we have a type `p1.S` with a parameterized method and
+a type `p2.HasIdentity` that also has a parameterized method.
+`p1.S` implements `p2.HasIdentity`.
+Therefore, the function `p3.CheckIdentity` can call `vi.Identity` with
+an `int` argument, which in the call from `p4.CheckSIdentity` will be
+a call to `p1.S.Identity[int]`.
+But package p3 does not know anything about the type `p1.S`.
+There may be no other call to `p1.S.Identity` elsewhere in the
+program.
+We need to instantiate `p1.S.Identity[int]` somewhere, but how?
+
+We could instantiate it at link time, but in the general case that
+requires the linker to traverse the complete call graph of the program
+to determine the set of types that might be passed to `CheckIdentity`.
+And even that traversal is not sufficient in the general case when
+type reflection gets involved, as reflection might look up methods
+based on strings input by the user.
+So in general instantiating parameterized methods in the linker might
+require instantiating every parameterized method for every possible
+type argument, which seems untenable.
+
+Or, we could instantiate it at run time.
+In general this means using some sort of JIT, or compiling the code to
+use some sort of reflection based approach.
+Either approach would be very complex to implement, and would be
+surprisingly slow at run time.
+
+Or, we could decide that parameterized methods do not, in fact,
+implement interfaces, but then it's much less clear why we need
+methods at all.
+If we disregard interfaces, any parameterized method can be
+implemented as a parameterized function.
+
+So while parameterized methods seem clearly useful at first glance, we
+would have to decide what they mean and how to implement that.
+
+##### No way to require pointer methods
+
+In some cases a parameterized function is naturally written such that
+it always invokes methods on addressable values.
+For example, this happens when calling a method on each element of a
+slice.
+In such a case, the function only requires that the method be in the
+slice element type's pointer method set.
+The type constraints described in this design  have no way to write
+that requirement.
+
+For example, consider a variant of the `Stringify` example we [showed
+earlier](#Using-a-constraint).
+
+```
+// Stringify2 calls the String method on each element of s,
+// and returns the results.
+func Stringify2[T Stringer](s []T) (ret []string) {
+	for i := range s {
+		ret = append(ret, s[i].String())
+	}
+	return ret
+}
+```
+
+Suppose we have a `[]bytes.Buffer` and we want to convert it into a
+`[]string`.
+The `Stringify2` function here won't help us.
+We want to write `Stringify2[bytes.Buffer]`, but we can't, because
+`bytes.Buffer` doesn't have a `String` method.
+The type that has a `String` method is `*bytes.Buffer`.
+Writing `Stringify2[*bytes.Buffer]` doesn't help because that function
+expects a `[]*bytes.Buffer`, but we have a `[]bytes.Buffer`.
+
+We discussed a similar case in the [pointer method
+example](#Pointer-method-example) above.
+There we used constraint type inference to help simplify the problem.
+Here that doesn't help, because `Stringify2` doesn't really care about
+calling a pointer method.
+It just wants a type that has a `String` method, and it's OK if the
+method is only in the pointer method set, not the value method set.
+But we also want to accept the case where the method is in the value
+method set, for example if we really do have a `[]*bytes.Buffer`.
+
+What we need is a way to say that the type constraint applies to
+either the pointer method set or the value method set.
+The body of the function would be required to only call the method on
+addressable values of the type.
+
+It's not clear how often this problem comes up in practice.
+
+##### No association between float and complex
+
+Constraint type inference lets us give a name to the element of a
+slice type, and to apply other similar type decompositions.
+However, there is no way to associate a float type and a complex type.
+For example, there is no way to write the predeclared `real`, `imag`,
+or `complex` functions with this design.
+There is no way to say "if the argument type is `complex64`, then the
+result type is `float32`."
+
+One possible approach here would be to permit `real(T)` as a type
+constraint meaning "the float type associated with the complex type
+`T`".
+Similarly, `complex(T)` would mean "the complex type associated with
+the floating point type `T`".
+Constraint type inference would simplify the call site.
+However, that would be unlike other type constraints.
+
+#### Discarded ideas
+
+This design is not perfect, and there may be ways to improve it.
+That said, there are many ideas that we've already considered in
+detail.
+This section lists some of those ideas in the hopes that it will help
+to reduce repetitive discussion.
+The ideas are presented in the form of a FAQ.
+
+##### What happened to contracts?
+
+An earlier draft design of generics implemented constraints using a
+new language construct called contracts.
+Type lists appeared only in contracts, rather than on interface
+types.
+However, many people had a hard time understanding the difference
+between contracts and interface types.
+It also turned out that contracts could be represented as a set of
+corresponding interfaces; there was no loss in expressive power
+without contracts.
+We decided to simplify the approach to use only interface types.
+
+##### Why not use methods instead of type lists?
+
+_Type lists are weird._
+_Why not write methods for all operators?_
+
+It is possible to permit operator tokens as method names, leading to
+methods such as `+(T) T`.
+Unfortunately, that is not sufficient.
+We would need some mechanism to describe a type that matches any
+integer type, for operations such as shifts `<<(integer) T` and
+indexing `[](integer) T` which are not restricted to a single int
+type.
+We would need an untyped boolean type for operations such as `==(T)
+untyped bool`.
+We would need to introduce new notation for operations such as
+conversions, or to express that one may range over a type, which would
+likely require some new syntax.
+We would need some mechanism to describe valid values of untyped
+constants.
+We would have to consider whether support for `<(T) bool` means that a
+generic function can also use `<=`, and similarly whether support for
+`+(T) T` means that a function can also use `++`.
+It might be possible to make this approach work but it's not
+straightforward.
+The approach used in this design seems simpler and relies on only one
+new syntactic construct (type lists) and one new name (`comparable`).
+
+##### Why not put type parameters on packages?
+
+We investigated this extensively.
+It becomes problematic when you want to write a `list` package, and
+you want that package to include a `Transform` function that converts
+a `List` of one element type to a `List` of another element type.
+It's very awkward for a function in one instantiation of a package to
+return a type that requires a different instantiation of the same
+package.
+
+It also confuses package boundaries with type definitions.
+There is no particular reason to think that the uses of generic types
+will break down neatly into packages.
+Sometimes they will, sometimes they won't.
+
+##### Why not use the syntax `F<T>` like C++ and Java?
+
+When parsing code within a function, such as `v := F<T>`, at the point
+of seeing the `<` it's ambiguous whether we are seeing a type
+instantiation or an expression using the `<` operator.
+This is very difficult to resolve without type information.
+
+For example, consider a statement like
+
+```
+	a, b = w < x, y > (z)
+```
+
+Without type information, it is impossible to decide whether the right
+hand side of the assignment is a pair of expressions (`w < x` and `y >
+(z)`), or whether it is a generic function instantiation and call that
+returns two result values (`(w<x, y>)(z)`).
+
+It is a key design decision of Go that parsing be possible without
+type information, which seems impossible when using angle brackets for
+generics.
+
+##### Why not use the syntax `F(T)`?
+
+An earlier version of this design used that syntax.
+It was workable but it introduced several parsing ambiguities.
+For example, when writing `var f func(x(T))` it wasn't clear whether
+this the type was a function with a single unnamed parameter of the
+instantiated type `x(T)` or whether it was a function with a parameter
+named `x` with type `(T)` (more usually written as `func(x T)`, but in
+this case with a parenthesized type).
+
+There were other ambiguities as well.
+For `[]T(v1)` and `[]T(v2){}`, at the point of the open parentheses we
+don't know whether this is a type conversion (of the value `v1` to the
+type `[]T`) or a type literal (whose type is the instantiated type
+`T(v2)`).
+For `interface { M(T) }` we don't know whether this an interface with
+a method `M` or an interface with an embedded instantiated interface
+`M(T)`.
+These ambiguities are solvable, by adding more parentheses, but
+awkward.
+
+Also some people were troubled by the number of parenthesized lists
+involved in declarations like `func F(T any)(v T)(r1, r2 T)` or in
+calls like `F(int)(1)`.
+
+##### Why not use `F«T»`?
+
+We considered it but we couldn't bring ourselves to require
+non-ASCII.
+
+##### Why not define constraints in a builtin package?
+
+_Instead of writing out type lists, use names like_
+_`constraints.Arithmetic` and `constraints.Comparable`._
+
+Listing all the possible combinations of types gets rather lengthy.
+It also introduces a new set of names that not only the writer of
+generic code, but, more importantly, the reader, must remember.
+One of the driving goals of this design is to introduce as few new
+names as possible.
+In this design we introduce only two new predeclared names,
+`comparable` and `any`.
+
+We expect that if people find such names useful, we can introduce a
+package `constraints` that defines those names in the form of
+constraints that can be used by other types and functions and embedded
+in other constraints.
+That will define the most useful names in the standard library while
+giving programmers the flexibility to use other combinations of types
+where appropriate.
+
+##### Why not permit type assertions on values whose type is a type parameter?
+
+In an earlier version of this design, we permitted using type
+assertions and type switches on variables whose type was a type
+parameter, or whose type was based on a type parameter.
+We removed this facility because it is always possible to convert a
+value of any type to the empty interface type, and then use a type
+assertion or type switch on that.
+Also, it was sometimes confusing that in a constraint with a type
+list, a type assertion or type switch would use the actual type
+argument, not the underlying type of the type argument (the difference
+is explained in the section on [identifying the matched predeclared
+type](#Identifying-the-matched-predeclared-type)).
+
+#### Comparison with Java
+
+Most complaints about Java generics center around type erasure.
+This design does not have type erasure.
+The reflection information for a generic type will include the full
+compile-time type information.
+
+In Java type wildcards (`List<? extends Number>`, `List<? super
+Number>`) implement covariance and contravariance.
+These concepts are missing from Go, which makes generic types much
+simpler.
+
+#### Comparison with C++
+
+C++ templates do not enforce any constraints on the type arguments
+(unless the concept proposal is adopted).
+This means that changing template code can accidentally break far-off
+instantiations.
+It also means that error messages are reported only at instantiation
+time, and can be deeply nested and difficult to understand.
+This design avoids these problems through mandatory and explicit
+constraints.
+
+C++ supports template metaprogramming, which can be thought of as
+ordinary programming done at compile time using a syntax that is
+completely different than that of non-template C++.
+This design has no similar feature.
+This saves considerable complexity while losing some power and run
+time efficiency.
+
+C++ uses two-phase name lookup, in which some names are looked up in
+the context of the template definition, and some names are looked up
+in the context of the template instantiation.
+In this design all names are looked up at the point where they are
+written.
+
+In practice, all C++ compilers compile each template at the point
+where it is instantiated.
+This can slow down compilation time.
+This design offers flexibility as to how to handle the compilation of
+generic functions.
+
+#### Comparison with Rust
+
+The generics described in this design are similar to generics in
+Rust.
+
+One difference is that in Rust the association between a trait bound
+and a type must be defined explicitly, either in the crate that
+defines the trait bound or the crate that defines the type.
+In Go terms, this would mean that we would have to declare somewhere
+whether a type satisfied a constraint.
+Just as Go types can satisfy Go interfaces without an explicit
+declaration, in this design Go type arguments can satisfy a constraint
+without an explicit declaration.
+
+Where this design uses type lists, the Rust standard library defines
+standard traits for operations like comparison.
+These standard traits are automatically implemented by Rust's
+primitive types, and can be implemented by user defined types as
+well.
+Rust provides a fairly extensive list of traits, at least 34, covering
+all of the operators.
+
+Rust supports type parameters on methods, which this design does not.
+
+## Examples
+
+The following sections are examples of how this design could be used.
+This is intended to address specific areas where people have created
+user experience reports concerned with Go's lack of generics.
+
+### Map/Reduce/Filter
+
+Here is an example of how to write map, reduce, and filter functions
+for slices.
+These functions are intended to correspond to the similar functions in
+Lisp, Python, Java, and so forth.
+
+```
+// Package slices implements various slice algorithms.
+package slices
+
+// Map turns a []T1 to a []T2 using a mapping function.
+// This function has two type parameters, T1 and T2.
+// This works with slices of any type.
+func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 {
+	r := make([]T2, len(s))
+	for i, v := range s {
+		r[i] = f(v)
+	}
+	return r
+}
+
+// Reduce reduces a []T1 to a single value using a reduction function.
+func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 {
+	r := initializer
+	for _, v := range s {
+		r = f(r, v)
+	}
+	return r
+}
+
+// Filter filters values from a slice using a filter function.
+// It returns a new slice with only the elements of s
+// for which f returned true.
+func Filter[T any](s []T, f func(T) bool) []T {
+	var r []T
+	for _, v := range s {
+		if f(v) {
+			r = append(r, v)
+		}
+	}
+	return r
+}
+```
+
+Here are some example calls of these functions.
+Type inference is used to determine the type arguments based on the
+types of the non-type arguments.
+
+```
+	s := []int{1, 2, 3}
+
+	floats := slices.Map(s, func(i int) float64 { return float64(i) })
+	// Now floats is []float64{1.0, 2.0, 3.0}.
+
+	sum := slices.Reduce(s, 0, func(i, j int) int { return i + j })
+	// Now sum is 6.
+
+	evens := slices.Filter(s, func(i int) bool { return i%2 == 0 })
+	// Now evens is []int{2}.
+```
+
+### Map keys
+
+Here is how to get a slice of the keys of any map.
+
+```
+// Package maps provides general functions that work for all map types.
+package maps
+
+// Keys returns the keys of the map m in a slice.
+// The keys will be returned in an unpredictable order.
+// This function has two type parameters, K and V.
+// Map keys must be comparable, so key has the predeclared
+// constraint comparable. Map values can be any type.
+func Keys[K comparable, V any](m map[K]V) []K {
+	r := make([]K, 0, len(m))
+	for k := range m {
+		r = append(r, k)
+	}
+	return r
+}
+```
+
+In typical use the map key and val types will be inferred.
+
+```
+	k := maps.Keys(map[int]int{1:2, 2:4})
+	// Now k is either []int{1, 2} or []int{2, 1}.
+```
+
+### Sets
+
+Many people have asked for Go's builtin map type to be extended, or
+rather reduced, to support a set type.
+Here is a type-safe implementation of a set type, albeit one that uses
+methods rather than operators like `[]`.
+
+```
+// Package sets implements sets of any comparable type.
+package sets
+
+// Set is a set of values.
+type Set[T comparable] map[T]struct{}
+
+// Make returns a set of some element type.
+func Make[T comparable]() Set[T] {
+	return make(Set[T])
+}
+
+// Add adds v to the set s.
+// If v is already in s this has no effect.
+func (s Set[T]) Add(v T) {
+	s[v] = struct{}{}
+}
+
+// Delete removes v from the set s.
+// If v is not in s this has no effect.
+func (s Set[T]) Delete(v T) {
+	delete(s, v)
+}
+
+// Contains reports whether v is in s.
+func (s Set[T]) Contains(v T) bool {
+	_, ok := s[v]
+	return ok
+}
+
+// Len reports the number of elements in s.
+func (s Set[T]) Len() int {
+	return len(s)
+}
+
+// Iterate invokes f on each element of s.
+// It's OK for f to call the Delete method.
+func (s Set[T]) Iterate(f func(T)) {
+	for v := range s {
+		f(v)
+	}
+}
+```
+
+Example use:
+
+```
+	// Create a set of ints.
+	// We pass int as a type argument.
+	// Then we write () because Make does not take any non-type arguments.
+	// We have to pass an explicit type argument to Make.
+	// Function argument type inference doesn't work because the
+	// type argument to Make is only used for a result parameter type.
+	s := sets.Make[int]()
+
+	// Add the value 1 to the set s.
+	s.Add(1)
+
+	// Check that s does not contain the value 2.
+	if s.Contains(2) { panic("unexpected 2") }
+```
+
+This example shows how to use this design to provide a compile-time
+type-safe wrapper around an existing API.
+
+### Sort
+
+Before the introduction of `sort.Slice`, a common complaint was the
+need for boilerplate definitions in order to use `sort.Sort`.
+With this design, we can add to the sort package as follows:
+
+```
+// Ordered is a type constraint that matches all ordered types.
+// (An ordered type is one that supports the < <= >= > operators.)
+// In practice this type constraint would likely be defined in
+// a standard library package.
+type Ordered interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr,
+		float32, float64,
+		string
+}
+
+// orderedSlice is an internal type that implements sort.Interface.
+// The Less method uses the < operator. The Ordered type constraint
+// ensures that T has a < operator.
+type orderedSlice[T Ordered] []T
+
+func (s orderedSlice[T]) Len() int           { return len(s) }
+func (s orderedSlice[T]) Less(i, j int) bool { return s[i] < s[j] }
+func (s orderedSlice[T]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+
+// OrderedSlice sorts the slice s in ascending order.
+// The elements of s must be ordered using the < operator.
+func OrderedSlice[T Ordered](s []T) {
+	// Convert s to the type orderedSlice[T].
+	// As s is []T, and orderedSlice[T] is defined as []T,
+	// this conversion is permitted.
+	// orderedSlice[T] implements sort.Interface,
+	// so can pass the result to sort.Sort.
+	// The elements will be sorted using the < operator.
+	sort.Sort(orderedSlice[T](s))
+}
+```
+
+Now we can write:
+
+```
+	s1 := []int32{3, 5, 2}
+	sort.OrderedSlice(s1)
+	// Now s1 is []int32{2, 3, 5}
+
+	s2 := []string{"a", "c", "b"})
+	sort.OrderedSlice(s2)
+	// Now s2 is []string{"a", "b", "c"}
+```
+
+Along the same lines, we can add a function for sorting using a
+comparison function, similar to `sort.Slice` but writing the function
+to take values rather than slice indexes.
+
+```
+// sliceFn is an internal type that implements sort.Interface.
+// The Less method calls the cmp field.
+type sliceFn[T any] struct {
+	s   []T
+	cmp func(T, T) bool
+}
+
+func (s sliceFn[T]) Len() int           { return len(s.s) }
+func (s sliceFn[T]) Less(i, j int) bool { return s.cmp(s.s[i], s.s[j]) }
+func (s sliceFn[T]) Swap(i, j int)      { s.s[i], s.s[j] = s.s[j], s.s[i] }
+
+// SliceFn sorts the slice s according to the function cmp.
+func SliceFn[T any](s []T, cmp func(T, T) bool) {
+	sort.Sort(sliceFn[E]{s, cmp})
+}
+```
+
+An example of calling this might be:
+
+```
+	var s []*Person
+	// ...
+	sort.SliceFn(s, func(p1, p2 *Person) bool { return p1.Name < p2.Name })
+```
+
+### Channels
+
+Many simple general purpose channel functions are never written,
+because they must be written using reflection and the caller must type
+assert the results.
+With this design they become straightforward to write.
+
+```
+// Package chans implements various channel algorithms.
+package chans
+
+import "runtime"
+
+// Drain drains any elements remaining on the channel.
+func Drain[T any](c <-chan T) {
+	for range c {
+	}
+}
+
+// Merge merges two channels of some element type into a single channel.
+func Merge[T any](c1, c2 <-chan T) <-chan T {
+	r := make(chan T)
+	go func(c1, c2 <-chan T, r chan<- T) {
+		defer close(r)
+		for c1 != nil || c2 != nil {
+			select {
+			case v1, ok := <-c1:
+				if ok {
+					r <- v1
+				} else {
+					c1 = nil
+				}
+			case v2, ok := <-c2:
+				if ok {
+					r <- v2
+				} else {
+					c2 = nil
+				}
+			}
+		}
+	}(c1, c2, r)
+	return r
+}
+
+// Ranger provides a convenient way to exit a goroutine sending values
+// when the receiver stops reading them.
+//
+// Ranger returns a Sender and a Receiver. The Receiver provides a
+// Next method to retrieve values. The Sender provides a Send method
+// to send values and a Close method to stop sending values. The Next
+// method indicates when the Sender has been closed, and the Send
+// method indicates when the Receiver has been freed.
+func Ranger[T any]() (*Sender[T], *Receiver[T]) {
+	c := make(chan T)
+	d := make(chan bool)
+	s := &Sender[T]{values: c, done: d}
+	r := &Receiver[T]{values: c, done: d}
+	// The finalizer on the receiver will tell the sender
+	// if the receiver stops listening.
+	runtime.SetFinalizer(r, r.finalize)
+	return s, r
+}
+
+// A Sender is used to send values to a Receiver.
+type Sender[T any] struct {
+	values chan<- T
+	done   <-chan bool
+}
+
+// Send sends a value to the receiver. It reports whether any more
+// values may be sent; if it returns false the value was not sent.
+func (s *Sender[T]) Send(v T) bool {
+	select {
+	case s.values <- v:
+		return true
+	case <-s.done:
+		// The receiver has stopped listening.
+		return false
+	}
+}
+
+// Close tells the receiver that no more values will arrive.
+// After Close is called, the Sender may no longer be used.
+func (s *Sender[T]) Close() {
+	close(s.values)
+}
+
+// A Receiver receives values from a Sender.
+type Receiver[T any] struct {
+	values <-chan T
+	done  chan<- bool
+}
+
+// Next returns the next value from the channel. The bool result
+// reports whether the value is valid. If the value is not valid, the
+// Sender has been closed and no more values will be received.
+func (r *Receiver[T]) Next() (T, bool) {
+	v, ok := <-r.values
+	return v, ok
+}
+
+// finalize is a finalizer for the receiver.
+// It tells the sender that the receiver has stopped listening.
+func (r *Receiver[T]) finalize() {
+	close(r.done)
+}
+```
+
+There is an example of using this function in the next section.
+
+### Containers
+
+One of the frequent requests for generics in Go is the ability to
+write compile-time type-safe containers.
+This design makes it easy to write a compile-time type-safe wrapper
+around an existing container; we won't write out an example for that.
+This design also makes it easy to write a compile-time type-safe
+container that does not use boxing.
+
+Here is an example of an ordered map implemented as a binary tree.
+The details of how it works are not too important.
+The important points are:
+
+* The code is written in a natural Go style, using the key and value
+  types where needed.
+* The keys and values are stored directly in the nodes of the tree,
+  not using pointers and not boxed as interface values.
+
+```
+// Package orderedmaps provides an ordered map, implemented as a binary tree.
+package orderedmaps
+
+import "chans"
+
+// Map is an ordered map.
+type Map[K, V any] struct {
+	root    *node[K, V]
+	compare func(K, K) int
+}
+
+// node is the type of a node in the binary tree.
+type node[K, V any] struct {
+	k           K
+	v           V
+	left, right *node[K, V]
+}
+
+// New returns a new map.
+// Since the type parameter V is only used for the result,
+// type inference does not work, and calls to New must always
+// pass explicit type arguments.
+func New[K, V any](compare func(K, K) int) *Map[K, V] {
+	return &Map[K, V]{compare: compare}
+}
+
+// find looks up k in the map, and returns either a pointer
+// to the node holding k, or a pointer to the location where
+// such a node would go.
+func (m *Map[K, V]) find(k K) **node[K, V] {
+	pn := &m.root
+	for *pn != nil {
+		switch cmp := m.compare(k, (*pn).k); {
+		case cmp < 0:
+			pn = &(*pn).left
+		case cmp > 0:
+			pn = &(*pn).right
+		default:
+			return pn
+		}
+	}
+	return pn
+}
+
+// Insert inserts a new key/value into the map.
+// If the key is already present, the value is replaced.
+// Reports whether this is a new key.
+func (m *Map[K, V]) Insert(k K, v V) bool {
+	pn := m.find(k)
+	if *pn != nil {
+		(*pn).v = v
+		return false
+	}
+	*pn = &node[K, V]{k: k, v: v}
+	return true
+}
+
+// Find returns the value associated with a key, or zero if not present.
+// The bool result reports whether the key was found.
+func (m *Map[K, V]) Find(k K) (V, bool) {
+	pn := m.find(k)
+	if *pn == nil {
+		var zero V // see the discussion of zero values, above
+		return zero, false
+	}
+	return (*pn).v, true
+}
+
+// keyValue is a pair of key and value used when iterating.
+type keyValue[K, V any] struct {
+	k K
+	v V
+}
+
+// InOrder returns an iterator that does an in-order traversal of the map.
+func (m *Map[K, V]) InOrder() *Iterator[K, V] {
+	type kv = keyValue[K, V] // convenient shorthand
+	sender, receiver := chans.Ranger[kv]()
+	var f func(*node[K, V]) bool
+	f = func(n *node[K, V]) bool {
+		if n == nil {
+			return true
+		}
+		// Stop sending values if sender.Send returns false,
+		// meaning that nothing is listening at the receiver end.
+		return f(n.left) &&
+			sender.Send(kv{n.k, n.v}) &&
+			f(n.right)
+	}
+	go func() {
+		f(m.root)
+		sender.Close()
+	}()
+	return &Iterator[K, V]{receiver}
+}
+
+// Iterator is used to iterate over the map.
+type Iterator[K, V any] struct {
+	r *chans.Receiver[keyValue[K, V]]
+}
+
+// Next returns the next key and value pair. The bool result reports
+// whether the values are valid. If the values are not valid, we have
+// reached the end.
+func (it *Iterator[K, V]) Next() (K, V, bool) {
+	kv, ok := it.r.Next()
+	return kv.k, kv.v, ok
+}
+```
+
+This is what it looks like to use this package:
+
+```
+import "container/orderedmaps"
+
+// Set m to an ordered map from string to string,
+// using strings.Compare as the comparison function.
+var m = orderedmaps.New[string, string](strings.Compare)
+
+// Add adds the pair a, b to m.
+func Add(a, b string) {
+	m.Insert(a, b)
+}
+```
+
+### Append
+
+The predeclared `append` function exists to replace the boilerplate
+otherwise required to grow a slice.
+Before `append` was added to the language, there was a function `Add`
+in the bytes package:
+
+```
+// Add appends the contents of t to the end of s and returns the result.
+// If s has enough capacity, it is extended in place; otherwise a
+// new array is allocated and returned.
+func Add(s, t []byte) []byte
+```
+
+`Add` appended two `[]byte` values together, returning a new slice.
+That was fine for `[]byte`, but if you had a slice of some other
+type, you had to write essentially the same code to append more
+values.
+If this design were available back then, perhaps we would not have
+added `append` to the language.
+Instead, we could write something like this:
+
+```
+// Package slices implements various slice algorithms.
+package slices
+
+// Append appends the contents of t to the end of s and returns the result.
+// If s has enough capacity, it is extended in place; otherwise a
+// new array is allocated and returned.
+func Append[T any](s []T, t ...T) []T {
+	lens := len(s)
+	tot := lens + len(t)
+	if tot < 0 {
+		panic("Append: cap out of range")
+	}
+	if tot > cap(s) {
+		news := make([]T, tot, tot + tot/2)
+		copy(news, s)
+		s = news
+	}
+	s = s[:tot]
+	copy(s[lens:], t)
+	return s
+}
+```
+
+That example uses the predeclared `copy` function, but that's OK, we
+can write that one too:
+
+```
+// Copy copies values from t to s, stopping when either slice is
+// full, returning the number of values copied.
+func Copy[T any](s, t []T) int {
+	i := 0
+	for ; i < len(s) && i < len(t); i++ {
+		s[i] = t[i]
+	}
+	return i
+}
+```
+
+These functions can be used as one would expect:
+
+```
+	s := slices.Append([]int{1, 2, 3}, 4, 5, 6)
+	// Now s is []int{1, 2, 3, 4, 5, 6}.
+	slices.Copy(s[3:], []int{7, 8, 9})
+	// Now s is []int{1, 2, 3, 7, 8, 9}
+```
+
+This code doesn't implement the special case of appending or copying a
+`string` to a `[]byte`, and it's unlikely to be as efficient as the
+implementation of the predeclared function.
+Still, this example shows that using this design would permit `append`
+and `copy` to be written generically, once, without requiring any
+additional special language features.
+
+### Metrics
+
+In a [Go experience
+report](https://medium.com/@sameer_74231/go-experience-report-for-generics-google-metrics-api-b019d597aaa4)
+Sameer Ajmani describes a metrics implementation.
+Each metric has a value and one or more fields.
+The fields have different types.
+Defining a metric requires specifying the types of the fields.
+The `Add` method takes the field types as arguments, and records an
+instance of that set of fields.
+The C++ implementation uses a variadic template.
+The Java implementation includes the number of fields in the name of
+the type.
+Both the C++ and Java implementations provide compile-time type-safe
+Add methods.
+
+Here is how to use this design to provide similar functionality in
+Go with a compile-time type-safe `Add` method.
+Because there is no support for a variadic number of type arguments,
+we must use different names for a different number of arguments, as in
+Java.
+This implementation only works for comparable types.
+A more complex implementation could accept a comparison function to
+work with arbitrary types.
+
+```
+// Package metrics provides a general mechanism for accumulating
+// metrics of different values.
+package metrics
+
+import "sync"
+
+// Metric1 accumulates metrics of a single value.
+type Metric1[T comparable] struct {
+	mu sync.Mutex
+	m  map[T]int
+}
+
+// Add adds an instance of a value.
+func (m *Metric1[T]) Add(v T) {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	if m.m == nil {
+		m.m = make(map[T]int)
+	}
+	m.m[v]++
+}
+
+// key2 is an internal type used by Metric2.
+type key2[T1, T2 comparable] struct {
+	f1 T1
+	f2 T2
+}
+
+// Metric2 accumulates metrics of pairs of values.
+type Metric2[T1, T2 comparable] struct {
+	mu sync.Mutex
+	m  map[key2[T1, T2]]int
+}
+
+// Add adds an instance of a value pair.
+func (m *Metric2[T1, T2]) Add(v1 T1, v2 T2) {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	if m.m == nil {
+		m.m = make(map[key2[T1, T2]]int)
+	}
+	m.m[key2[T1, T2]{v1, v2}]++
+}
+
+// key3 is an internal type used by Metric3.
+type key3[T1, T2, T3 comparable] struct {
+	f1 T1
+	f2 T2
+	f3 T3
+}
+
+// Metric3 accumulates metrics of triples of values.
+type Metric3[T1, T2, T3 comparable] struct {
+	mu sync.Mutex
+	m  map[key3[T1, T2, T3]]int
+}
+
+// Add adds an instance of a value triplet.
+func (m *Metric3[T1, T2, T3]) Add(v1 T1, v2 T2, v3 T3) {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	if m.m == nil {
+		m.m = make(map[key3[T1, T2, T3]]int)
+	}
+	m.m[key3[T1, T2, T3]{v1, v2, v3}]++
+}
+
+// Repeat for the maximum number of permitted arguments.
+```
+
+Using this package looks like this:
+
+```
+import "metrics"
+
+var m = metrics.Metric2[string, int]{}
+
+func F(s string, i int) {
+	m.Add(s, i) // this call is type checked at compile time
+}
+```
+
+This implementation has a certain amount of repetition due to the lack
+of support for variadic type parameters.
+Using the package, though, is easy and type safe.
+
+### List transform
+
+While slices are efficient and easy to use, there are occasional cases
+where a linked list is appropriate.
+This example primarily shows transforming a linked list of one type to
+another type, as an example of using different instantiations of the
+same generic type.
+
+```
+// Package lists provides a linked list of any type.
+package lists
+
+// List is a linked list.
+type List[T any] struct {
+	head, tail *element[T]
+}
+
+// An element is an entry in a linked list.
+type element[T any] struct {
+	next *element[T]
+	val  T
+}
+
+// Push pushes an element to the end of the list.
+func (lst *List[T]) Push(v T) {
+	if lst.tail == nil {
+		lst.head = &element[T]{val: v}
+		lst.tail = lst.head
+	} else {
+		lst.tail.next = &element[T]{val: v }
+		lst.tail = lst.tail.next
+	}
+}
+
+// Iterator ranges over a list.
+type Iterator[T any] struct {
+	next **element[T]
+}
+
+// Range returns an Iterator starting at the head of the list.
+func (lst *List[T]) Range() *Iterator[T] {
+	return Iterator[T]{next: &lst.head}
+}
+
+// Next advances the iterator.
+// It reports whether there are more elements.
+func (it *Iterator[T]) Next() bool {
+	if *it.next == nil {
+		return false
+	}
+	it.next = &(*it.next).next
+	return true
+}
+
+// Val returns the value of the current element.
+// The bool result reports whether the value is valid.
+func (it *Iterator[T]) Val() (T, bool) {
+	if *it.next == nil {
+		var zero T
+		return zero, false
+	}
+	return (*it.next).val, true
+}
+
+// Transform runs a transform function on a list returning a new list.
+func Transform[T1, T2 any](lst *List[T1], f func(T1) T2) *List[T2] {
+	ret := &List[T2]{}
+	it := lst.Range()
+	for {
+		if v, ok := it.Val(); ok {
+			ret.Push(f(v))
+		}
+		if !it.Next() {
+			break
+		}
+	}
+	return ret
+}
+```
+
+### Dot product
+
+A generic dot product implementation that works for slices of any
+numeric type.
+
+```
+// Numeric is a constraint that matches any numeric type.
+// It would likely be in a constraints package in the standard library.
+type Numeric interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr,
+		float32, float64,
+		complex64, complex128
+}
+
+// DotProduct returns the dot product of two slices.
+// This panics if the two slices are not the same length.
+func DotProduct[T Numeric](s1, s2 []T) T {
+	if len(s1) != len(s2) {
+		panic("DotProduct: slices of unequal length")
+	}
+	var r T
+	for i := range s1 {
+		r += s1[i] * s2[i]
+	}
+	return r
+}
+```
+
+(Note: the generics implementation approach may affect whether
+`DotProduct` uses FMA, and thus what the exact results are when using
+floating point types.
+It's not clear how much of a problem this is, or whether there is any
+way to fix it.)
+
+### Absolute difference
+
+Compute the absolute difference between two numeric values, by using
+an `Abs` method.
+This uses the same `Numeric` constraint defined in the last example.
+
+This example uses more machinery than is appropriate for the simple
+case of computing the absolute difference.
+It is intended to show how the common part of algorithms can be
+factored into code that uses methods, where the exact definition of
+the methods can vary based on the kind of type being used.
+
+```
+// NumericAbs matches numeric types with an Abs method.
+type NumericAbs[T any] interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr,
+		float32, float64,
+		complex64, complex128
+	Abs() T
+}
+
+// AbsDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func AbsDifference[T NumericAbs](a, b T) T {
+	d := a - b
+	return d.Abs()
+}
+```
+
+We can define an `Abs` method appropriate for different numeric types.
+
+```
+// OrderedNumeric matches numeric types that support the < operator.
+type OrderedNumeric interface {
+	type int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr,
+		float32, float64
+}
+
+// Complex matches the two complex types, which do not have a < operator.
+type Complex interface {
+	type complex64, complex128
+}
+
+// OrderedAbs is a helper type that defines an Abs method for
+// ordered numeric types.
+type OrderedAbs[T OrderedNumeric] T
+
+func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
+	if a < 0 {
+		return -a
+	}
+	return a
+}
+
+// ComplexAbs is a helper type that defines an Abs method for
+// complex types.
+type ComplexAbs[T Complex] T
+
+func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
+	d := math.Hypot(float64(real(a)), float64(imag(a)))
+	return ComplexAbs[T](complex(d, 0))
+}
+```
+
+We can then define functions that do the work for the caller by
+converting to and from the types we just defined.
+
+```
+// OrderedAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of an ordered type.
+func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
+	return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
+}
+
+// ComplexAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of a complex type.
+func ComplexAbsDifference[T Complex](a, b T) T {
+	return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
+}
+```
+
+It's worth noting that this design is not powerful enough to write
+code like the following:
+
+```
+// This function is INVALID.
+func GeneralAbsDifference[T Numeric](a, b T) T {
+	switch (interface{})(a).(type) {
+	case int, int8, int16, int32, int64,
+		uint, uint8, uint16, uint32, uint64, uintptr,
+		float32, float64:
+		return OrderedAbsDifference(a, b) // INVALID
+	case complex64, complex128:
+		return ComplexAbsDifference(a, b) // INVALID
+	}
+}
+```
+
+The calls to `OrderedAbsDifference` and `ComplexAbsDifference` are
+invalid, because not all the types that implement the `Numeric`
+constraint can implement the `OrderedNumeric` or `Complex`
+constraints.
+Although the type switch means that this code would conceptually work
+at run time, there is no support for writing this code at compile
+time.
+This is another way of expressing one of the omissions listed above:
+this design does not provide for specialization.
+
+## Acknowledgements
+
+We'd like to thank many people on the Go team, many contributors to
+the Go issue tracker, and all the people who have shared their ideas
+and their feedback on earlier design drafts.
+We read all of it, and we're grateful.
+
+For this version of the proposal in particular we received detailed
+feedback from Josh Bleecher-Snyder, Jon Bodner, Dave Cheney, Jaana
+Dogan, Kevin Gillette, Mitchell Hashimoto, Chris Hines, Bill Kennedy,
+Ayke van Laethem, Daniel Martí, Elena Morozova, Roger Peppe, and Ronna
+Steinberg.
+
+## Appendix
+
+This appendix covers various details of the design that don't seem
+significant enough to cover in earlier sections.
+
+### Generic type aliases
+
+A type alias may refer to a generic type, but the type alias may not
+have its own parameters.
+This restriction exists because it is unclear how to handle a type
+alias with type parameters that have constraints.
+
+```
+type VectorAlias = Vector
+```
+
+In this case uses of the type alias will have to provide type
+arguments appropriate for the generic type being aliased.
+
+```
+var v VectorAlias[int]
+```
+
+Type aliases may also refer to instantiated types.
+
+```
+type VectorInt = Vector[int]
+```
+
+### Instantiating a function
+
+Go normally permits you to refer to a function without passing any
+arguments, producing a value of function type.
+You may not do this with a function that has type parameters; all type
+arguments must be known at compile time.
+That said, you can instantiate the function, by passing type
+arguments, but you don't have to call the instantiation.
+This will produce a function value with no type parameters.
+
+```
+// PrintInts is type func([]int).
+var PrintInts = Print[int]
+```
+
+### Embedded type parameter
+
+When a generic type is a struct, and the type parameter is
+embedded as a field in the struct, the name of the field is the name
+of the type parameter.
+
+```
+// A Lockable is a value that may be safely simultaneously accessed
+// from multiple goroutines via the Get and Set methods.
+type Lockable[T any] struct {
+	T
+	mu sync.Mutex
+}
+
+// Get returns the value stored in a Lockable.
+func (l *Lockable[T]) Get() T {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	return l.T
+}
+
+// Set sets the value in a Lockable.
+func (l *Lockable[T]) Set(v T) {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	l.T = v
+}
+```
+
+### Embedded type parameter methods
+
+When a generic type is a struct, and the type parameter is embedded as
+a field in the struct, any methods of the type parameter's constraint
+are promoted to be methods of the struct.
+(For purposes of [selector
+resolution](https://golang.org/ref/spec#Selectors), these methods are
+treated as being at depth 0 of the type parameter, even if in the
+actual type argument the methods were themselves promoted from an
+embedded type.)
+
+```
+// NamedInt is an int with a name. The name can be any type with
+// a String method.
+type NamedInt[Name fmt.Stringer] struct {
+	Name
+	val int
+}
+
+// Name returns the name of a NamedInt.
+func (ni NamedInt[Name]) Name() string {
+	// The String method is promoted from the embedded Name.
+	return ni.String()
+}
+```
+
+### Embedded instantiated type
+
+When embedding an instantiated type, the name of the field is the name
+of type without the type arguments.
+
+```
+type S struct {
+	T[int] // field name is T
+}
+
+func F(v S) int {
+	return v.T // not v.T[int]
+}
+```
+
+### Generic types as type switch cases
+
+A generic type may be used as the type in a type assertion or as a
+case in a type switch.
+
+Here are some trivial examples:
+
+```
+func Assertion[T any](v interface{}) (T, bool) {
+	t, ok := v.(T)
+	return t, ok
+}
+
+func Switch[T any](v interface{}) (T, bool) {
+	switch v := v.(type) {
+	case T:
+		return v, true
+	default:
+		var zero T
+		return zero, false
+	}
+}
+```
+
+In a type switch, it's OK if a generic type turns out to duplicate
+some other case in the type switch.
+The first matching case is chosen.
+
+```
+func Switch2[T any](v interface{}) int {
+	switch v.(type) {
+	case T:
+		return 0
+	case string:
+		return 1
+	default:
+		return 2
+	}
+}
+
+// S2a will be set to 0.
+var S2a = Switch2[string]("a string")
+
+// S2b will be set to 1.
+var S2b = Switch2[int]("another string")
+```
+
+### Type inference for composite literals
+
+This is a feature we are not suggesting now, but could consider for
+later versions of the language.
+
+We could also consider supporting type inference for composite
+literals of generic types.
+
+```
+type Pair[T any] struct { f1, f2 T }
+var V = Pair{1, 2} // inferred as Pair(int){1, 2}
+```
+
+It's not clear how often this will arise in real code.
+
+### Type inference for generic function arguments
+
+This is a feature we are not suggesting now, but could consider for
+later versions of the language.
+
+In the following example, consider the call to `Find` in `FindClose`.
+Type inference can determine that the type argument to `Find` is `T4`,
+and from that we know that the type of the final argument must be
+`func(T4, T4) bool`, and from that we could deduce that the type
+argument to `IsClose` must also be `T4`.
+However, the type inference algorithm described earlier cannot do
+that, so we must explicitly write `IsClose[T4]`.
+
+This may seem esoteric at first, but it comes up when passing generic
+functions to generic `Map` and `Filter` functions.
+
+```
+// Differ has a Diff method that returns how different a value is.
+type Differ[T1 any] interface {
+	Diff(T1) int
+}
+
+// IsClose returns whether a and b are close together, based on Diff.
+func IsClose[T2 Differ](a, b T2) bool {
+	return a.Diff(b) < 2
+}
+
+// Find returns the index of the first element in s that matches e,
+// based on the cmp function. It returns -1 if no element matches.
+func Find[T3 any](s []T3, e T3, cmp func(a, b T3) bool) int {
+	for i, v := range s {
+		if cmp(v, e) {
+			return i
+		}
+	}
+	return -1
+}
+
+// FindClose returns the index of the first element in s that is
+// close to e, based on IsClose.
+func FindClose[T4 Differ](s []T4, e T4) int {
+	// With the current type inference algorithm we have to
+	// explicitly write IsClose[T4] here, although it
+	// is the only type argument we could possibly use.
+	return Find(s, e, IsClose[T4])
+}
+```
+
+### Reflection on type arguments
+
+Although we don't suggest changing the reflect package, one
+possibility to consider for the future would be to add two new
+methods to `reflect.Type`: `NumTypeArgument() int` would return the
+number of type arguments to a type, and `TypeArgument(i) Type` would
+return the i'th type argument.
+`NumTypeArgument` would return non-zero for an instantiated generic
+type.
+Similar methods could be defined for `reflect.Value`, for which
+`NumTypeArgument` would return non-zero for an instantiated generic
+function.
+There might be programs that care about this information.
diff --git a/design/go2draft-contracts.md b/design/go2draft-contracts.md
index 07760c2..9cb83ee 100644
--- a/design/go2draft-contracts.md
+++ b/design/go2draft-contracts.md
@@ -7,8 +7,8 @@
 ## Superseded
 
 We will not be pursuing the approach outlined in this design draft.
-It has been replaced by a [new design
-draft](https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md).
+It has been replaced by a [new
+proposal](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md).
 This document exists for historical context.
 
 ## Abstract
diff --git a/design/go2draft-type-parameters.md b/design/go2draft-type-parameters.md
index 2325c32..06d7d28 100644
--- a/design/go2draft-type-parameters.md
+++ b/design/go2draft-type-parameters.md
@@ -1,3993 +1,4 @@
 # Type Parameters - Draft Design
 
-Ian Lance Taylor\
-Robert Griesemer\
-January 11, 2021
-
-## Abstract
-
-We suggest extending the Go language to add optional type parameters
-to type and function declarations.
-Type parameters are constrained by interface types.
-Interface types, when used as type constraints, permit listing the set
-of types that may be assigned to them.
-Type inference via a unification algorithm permits omitting type
-arguments from function calls in many cases.
-The design is fully backward compatible with Go 1.
-
-## How to read this design draft
-
-This document is long.
-Here is some guidance on how to read it.
-
-* We start with a high level overview, describing the concepts very
-  briefly.
-* We then explain the full design starting from scratch, introducing
-  the details as we need them, with simple examples.
-* After the design is completely described, we discuss implementation,
-  some issues with the design, and a comparison with other approaches
-  to generics.
-* We then present several complete examples of how this design would
-  be used in practice.
-* Following the examples some minor details are discussed in an
-  appendix.
-
-## Very high level overview
-
-This section explains the changes suggested by the design draft very
-briefly.
-This section is intended for people who are already familiar with how
-generics would work in a language like Go.
-These concepts will be explained in detail in the following sections.
-
-* Functions can have an additional type parameter list that uses
-  square brackets but otherwise looks like an ordinary parameter list:
-  `func F[T any](p T) { ... }`.
-* These type parameters can be used by the regular parameters and in
-  the function body.
-* Types can also have a type parameter list: `type M[T any] []T`.
-* Each type parameter has a type constraint, just as each ordinary
-  parameter has a type: `func F[T Constraint](p T) { ... }`.
-* Type constraints are interface types.
-* The new predeclared name `any` is a type constraint that permits any
-  type.
-* Interface types used as type constraints can have a list of
-  predeclared types; only type arguments that match one of those types
-  satisfy the constraint.
-* Generic functions may only use operations permitted by the type
-  constraint.
-* Using a generic function or type requires passing type arguments.
-* Type inference permits omitting the type arguments of a function
-  call in common cases.
-
-In the following sections we work through each of these language
-changes in great detail.
-You may prefer to skip ahead to the [examples](#Examples) to see what
-generic code written to this design draft will look like in practice.
-
-## Background
-
-There have been many [requests to add additional support for generic
-programming](https://github.com/golang/go/wiki/ExperienceReports#generics)
-in Go.
-There has been extensive discussion on
-[the issue tracker](https://golang.org/issue/15292) and on
-[a living document](https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/view).
-
-This design draft suggests extending the Go language to add a form of
-parametric polymorphism, where the type parameters are bounded not by
-a declared subtyping relationship (as in some object oriented
-languages) but by explicitly defined structural constraints.
-
-This version of the design draft has many similarities to the one
-presented on July 31, 2019, but contracts have been removed and
-replaced by interface types, and the syntax has changed.
-
-There have been several proposals for adding type parameters, which
-can be found through the links above.
-Many of the ideas presented here have appeared before.
-The main new features described here are the syntax and the careful
-examination of interface types as constraints.
-
-This design does not support template metaprogramming or any other
-form of compile time programming.
-
-As the term _generic_ is widely used in the Go community, we will
-use it below as a shorthand to mean a function or type that takes type
-parameters.
-Don't confuse the term generic as used in this design with the same
-term in other languages like C++, C#, Java, or Rust; they have
-similarities but are not the same.
-
-## Design
-
-We will describe the complete design in stages based on simple
-examples.
-
-### Type parameters
-
-Generic code is written using abstract data types that we call _type
-parameters_.
-When running the generic code, the type parameters are replaced by
-_type arguments_.
-
-Here is a function that prints out each element of a slice, where the
-element type of the slice, here called `T`, is unknown.
-This is a trivial example of the kind of function we want to permit in
-order to support generic programming.
-(Later we'll also discuss [generic types](#Generic-types)).
-
-```
-// Print prints the elements of a slice.
-// It should be possible to call this with any slice value.
-func Print(s []T) { // Just an example, not the suggested syntax.
-	for _, v := range s {
-		fmt.Println(v)
-	}
-}
-```
-
-With this approach, the first decision to make is: how should the type
-parameter `T` be declared?
-In a language like Go, we expect every identifier to be declared in
-some way.
-
-Here we make a design decision: type parameters are similar to
-ordinary non-type function parameters, and as such should be listed
-along with other parameters.
-However, type parameters are not the same as non-type parameters, so
-although they appear in the list of parameters we want to distinguish
-them.
-That leads to our next design decision: we define an additional
-optional parameter list describing type parameters.
-
-This type parameter list appears before the regular parameters.
-To distinguish the type parameter list from the regular parameter
-list, the type parameter list uses square brackets rather than
-parentheses.
-Just as regular parameters have types, type parameters have
-meta-types, also known as constraints.
-We will discuss the details of constraints later; for now, we will
-just note that `any` is a valid constraint, meaning that any type is
-permitted.
-
-```
-// Print prints the elements of any slice.
-// Print has a type parameter T and has a single (non-type)
-// parameter s which is a slice of that type parameter.
-func Print[T any](s []T) {
-	// same as above
-}
-```
-
-This says that within the function `Print` the identifier `T` is a
-type parameter, a type that is currently unknown but that will be
-known when the function is called.
-The `any` means that `T` can be any type at all.
-As seen above, the type parameter may be used as a type when
-describing the types of the ordinary non-type parameters.
-It may also be used as a type within the body of the function.
-
-Unlike regular parameter lists, in type parameter lists names are
-required for the type parameters.
-This avoids a syntactic ambiguity, and, as it happens, there is no
-reason to ever omit the type parameter names.
-
-Since `Print` has a type parameter, any call of `Print` must provide a
-type argument.
-Later we will see how this type argument can usually be deduced from
-the non-type argument, by using [type inference](#Type-inference).
-For now, we'll pass the type argument explicitly.
-Type arguments are passed much like type parameters are declared: as a
-separate list of arguments.
-As with the type parameter list, the list of type arguments uses
-square brackets.
-
-```
-	// Call Print with a []int.
-	// Print has a type parameter T, and we want to pass a []int,
-	// so we pass a type argument of int by writing Print[int].
-	// The function Print[int] expects a []int as an argument.
-	Print[int]([]int{1, 2, 3})
-
-	// This will print:
-	// 1
-	// 2
-	// 3
-```
-
-### Constraints
-
-Let's make our example slightly more complicated.
-Let's turn it into a function that converts a slice of any type into a
-`[]string` by calling a `String` method on each element.
-
-```
-// This function is INVALID.
-func Stringify[T any](s []T) (ret []string) {
-	for _, v := range s {
-		ret = append(ret, v.String()) // INVALID
-	}
-	return ret
-}
-```
-
-This might seem OK at first glance, but in this example `v` has type
-`T`, and `T` can be any type.
-This means that `T` need not have a `String` method.
-So the call to `v.String()` is invalid.
-
-Naturally, the same issue arises in other languages that support
-generic programming.
-In C++, for example, a generic function (in C++ terms, a function
-template) can call any method on a value of generic type.
-That is, in the C++ approach, calling `v.String()` is fine.
-If the function is called with a type argument that does not have a
-`String` method, the error is reported when compiling the call to
-`v.String` with that type argument.
-These errors can be lengthy, as there may be several layers of generic
-function calls before the error occurs, all of which must be reported
-to understand what went wrong.
-
-The C++ approach would be a poor choice for Go.
-One reason is the style of the language.
-In Go we don't refer to names, such as, in this case, `String`, and
-hope that they exist.
-Go resolves all names to their declarations when they are seen.
-
-Another reason is that Go is designed to support programming at
-scale.
-We must consider the case in which the generic function definition
-(`Stringify`, above) and the call to the generic function (not shown,
-but perhaps in some other package) are far apart.
-In general, all generic code expects the type arguments to meet
-certain requirements.
-We refer to these requirements as _constraints_ (other languages have
-similar ideas known as type bounds or trait bounds or concepts).
-In this case, the constraint is pretty obvious: the type has to have a
-`String() string` method.
-In other cases it may be much less obvious.
-
-We don't want to derive the constraints from whatever `Stringify`
-happens to do (in this case, call the `String` method).
-If we did, a minor change to `Stringify` might change the
-constraints.
-That would mean that a minor change could cause code far away, that
-calls the function, to unexpectedly break.
-It's fine for `Stringify` to deliberately change its constraints, and
-force callers to change.
-What we want to avoid is `Stringify` changing its constraints
-accidentally.
-
-This means that the constraints must set limits on both the type
-arguments passed by the caller and the code in the generic function.
-The caller may only pass type arguments that satisfy the constraints.
-The generic function may only use those values in ways that are
-permitted by the constraints.
-This is an important rule that we believe should apply to any attempt
-to define generic programming in Go: generic code can only use
-operations that its type arguments are known to implement.
-
-### Operations permitted for any type
-
-Before we discuss constraints further, let's briefly note what happens
-when the constraint is `any`.
-If a generic function uses the `any` constraint for a type parameter,
-as is the case for the `Print` method above, then any type argument is
-permitted for that parameter.
-The only operations that the generic function can use with values of
-that type parameter are those operations that are permitted for values
-of any type.
-In the example above, the `Print` function declares a variable `v`
-whose type is the type parameter `T`, and it passes that variable to a
-function.
-
-The operations permitted for any type are:
-
-* declare variables of those types
-* assign other values of the same type to those variables
-* pass those variables to functions or return them from functions
-* take the address of those variables
-* convert or assign values of those types to the type `interface{}`
-* convert a value of type `T` to type `T` (permitted but useless)
-* use a type assertion to convert an interface value to the type
-* use the type as a case in a type switch
-* define and use composite types that use those types, such as a slice
-  of that type
-* pass the type to some predeclared functions such as `new`
-
-It's possible that future language changes will add other such
-operations, though none are currently anticipated.
-
-### Defining constraints
-
-Go already has a construct that is close to what we need for a
-constraint: an interface type.
-An interface type is a set of methods.
-The only values that can be assigned to a variable of interface type
-are those whose types implement the same methods.
-The only operations that can be done with a value of interface type,
-other than operations permitted for any type, are to call the
-methods.
-
-Calling a generic function with a type argument is similar to
-assigning to a variable of interface type: the type argument must
-implement the constraints of the type parameter.
-Writing a generic function is like using values of interface type: the
-generic code can only use the operations permitted by the constraint
-(or operations that are permitted for any type).
-
-Therefore, in this design, constraints are simply interface types.
-Implementing a constraint means implementing the interface type.
-(Later we'll see how to define constraints for operations other than
-method calls, such as [binary operators](#Operators)).
-
-For the `Stringify` example, we need an interface type with a `String`
-method that takes no arguments and returns a value of type `string`.
-
-```
-// Stringer is a type constraint that requires the type argument to have
-// a String method and permits the generic function to call String.
-// The String method should return a string representation of the value.
-type Stringer interface {
-	String() string
-}
-```
-
-(It doesn't matter for this discussion, but this defines the same
-interface as the standard library's `fmt.Stringer` type, and  real
-code would likely simply use `fmt.Stringer`.)
-
-### The `any` constraint
-
-Now that we know that constraints are simply interface types, we can
-explain what `any` means as a constraint.
-As shown above, the `any` constraint permits any type as a type
-argument and only permits the function to use the operations permitted
-for any type.
-The interface type for that is the empty interface: `interface{}`.
-So we could write the `Print` example as
-
-```
-// Print prints the elements of any slice.
-// Print has a type parameter T and has a single (non-type)
-// parameter s which is a slice of that type parameter.
-func Print[T interface{}](s []T) {
-	// same as above
-}
-```
-
-However, it's tedious to have to write `interface{}` every time you
-write a generic function that doesn't impose constraints on its type
-parameters.
-So in this design we suggest a type constraint `any` that is
-equivalent to `interface{}`.
-This will be a predeclared name, implicitly declared in the universe
-block.
-It will not be valid to use `any` as anything other than a type
-constraint.
-
-(Note: clearly we could make `any` generally available as an alias for
-`interface{}`, or as a new defined type defined as `interface{}`.
-However, we don't want this design draft, which is about generics, to
-lead to a possibly significant change to non-generic code.
-Adding `any` as a general purpose name for `interface{}` can and
-should be [discussed separately](https://golang.org/issue/33232)).
-
-### Using a constraint
-
-For a generic function, a constraint can be thought of as the type of
-the type argument: a meta-type.
-As shown above, constraints appear in the type parameter list as the
-meta-type of a type parameter.
-
-```
-// Stringify calls the String method on each element of s,
-// and returns the results.
-func Stringify[T Stringer](s []T) (ret []string) {
-	for _, v := range s {
-		ret = append(ret, v.String())
-	}
-	return ret
-}
-```
-
-The single type parameter `T` is followed by the constraint that
-applies to `T`, in this case `Stringer`.
-
-### Multiple type parameters
-
-Although the `Stringify` example uses only a single type parameter,
-functions may have multiple type parameters.
-
-```
-// Print2 has two type parameters and two non-type parameters.
-func Print2[T1, T2 any](s1 []T1, s2 []T2) { ... }
-```
-
-Compare this to
-
-```
-// Print2Same has one type parameter and two non-type parameters.
-func Print2Same[T any](s1 []T, s2 []T) { ... }
-```
-
-In `Print2` `s1` and `s2` may be slices of different types.
-In `Print2Same` `s1` and `s2` must be slices of the same element
-type.
-
-Just as each ordinary parameter may have its own type, each type
-parameter may have its own constraint.
-
-```
-// Stringer is a type constraint that requires a String method.
-// The String method should return a string representation of the value.
-type Stringer interface {
-	String() string
-}
-
-// Plusser is a type constraint that requires a Plus method.
-// The Plus method is expected to add the argument to an internal
-// string and return the result.
-type Plusser interface {
-	Plus(string) string
-}
-
-// ConcatTo takes a slice of elements with a String method and a slice
-// of elements with a Plus method. The slices should have the same
-// number of elements. This will convert each element of s to a string,
-// pass it to the Plus method of the corresponding element of p,
-// and return a slice of the resulting strings.
-func ConcatTo[S Stringer, P Plusser](s []S, p []P) []string {
-	r := make([]string, len(s))
-	for i, v := range s {
-		r[i] = p[i].Plus(v.String())
-	}
-	return r
-}
-```
-
-A single constraint can be used for multiple type parameters, just as
-a single type can be used for multiple non-type function parameters.
-The constraint applies to each type parameter separately.
-
-```
-// Stringify2 converts two slices of different types to strings,
-// and returns the concatenation of all the strings.
-func Stringify2[T1, T2 Stringer](s1 []T1, s2 []T2) string {
-	r := ""
-	for _, v1 := range s1 {
-		r += v1.String()
-	}
-	for _, v2 := range s2 {
-		r += v2.String()
-	}
-	return r
-}
-```
-
-### Generic types
-
-We want more than just generic functions: we also want generic types.
-We suggest that types be extended to take type parameters.
-
-```
-// Vector is a name for a slice of any element type.
-type Vector[T any] []T
-```
-
-A type's type parameters are just like a function's type parameters.
-
-Within the type definition, the type parameters may be used like any
-other type.
-
-To use a generic type, you must supply type arguments.
-This is called _instantiation_.
-The type arguments appear in square brackets, as usual.
-When we instantiate a type by supplying type arguments for the type
-parameters, we produce a type in which each use of a type parameter in
-the type definition is replaced by the corresponding type argument.
-
-```
-// v is a Vector of int values.
-//
-// This is similar to pretending that "Vector[int]" is a valid identifier,
-// and writing
-//   type "Vector[int]" []int
-//   var v "Vector[int]"
-// All uses of Vector[int] will refer to the same "Vector[int]" type.
-//
-var v Vector[int]
-```
-
-Generic types can have methods.
-The receiver type of a method must declare the same number of type
-parameters as are declared in the receiver type's definition.
-They are declared without any constraint.
-
-```
-// Push adds a value to the end of a vector.
-func (v *Vector[T]) Push(x T) { *v = append(*v, x) }
-```
-
-The type parameters listed in a method declaration need not have the
-same names as the type parameters in the type declaration.
-In particular, if they are not used by the method, they can be `_`.
-
-A generic type can refer to itself in cases where a type can
-ordinarily refer to itself, but when it does so the type arguments
-must be the type parameters, listed in the same order.
-This restriction prevents infinite recursion of type instantiation.
-
-```
-// List is a linked list of values of type T.
-type List[T any] struct {
-	next *List[T] // this reference to List[T] is OK
-	val  T
-}
-
-// This type is INVALID.
-type P[T1, T2 any] struct {
-	F *P[T2, T1] // INVALID; must be [T1, T2]
-}
-```
-
-This restriction applies to both direct and indirect references.
-
-```
-// ListHead is the head of a linked list.
-type ListHead[T any] struct {
-	head *ListElement[T]
-}
-
-// ListElement is an element in a linked list with a head.
-// Each element points back to the head.
-type ListElement[T any] struct {
-	next *ListElement[T]
-	val  T
-	// Using ListHead[T] here is OK.
-	// ListHead[T] refers to ListElement[T] refers to ListHead[T].
-	// Using ListHead[int] would not be OK, as ListHead[T]
-	// would have an indirect reference to ListHead[int].
-	head *ListHead[T]
-}
-```
-
-(Note: with more understanding of how people want to write code, it
-may be possible to relax this rule to permit some cases that use
-different type arguments.)
-
-The type parameter of a generic type may have constraints other than
-`any`.
-
-```
-// StringableVector is a slice of some type, where the type
-// must have a String method.
-type StringableVector[T Stringer] []T
-
-func (s StringableVector[T]) String() string {
-	var sb strings.Builder
-	for i, v := range s {
-		if i > 0 {
-			sb.WriteString(", ")
-		}
-		// It's OK to call v.String here because v is of type T
-		// and T's constraint is Stringer.
-		sb.WriteString(v.String())
-	}
-	return sb.String()
-}
-```
-
-### Methods may not take additional type arguments
-
-Although methods of a generic type may use the type's parameters,
-methods may not themselves have additional type parameters.
-Where it would be useful to add type arguments to a method, people
-will have to write a suitably parameterized top-level function.
-
-There is more discussion of this in [the issues
-section](#No-parameterized-methods).
-
-### Operators
-
-As we've seen, we are using interface types as constraints.
-Interface types provide a set of methods, and nothing else.
-This means that with what we've seen so far, the only thing that
-generic functions can do with values of type parameters, other than
-operations that are permitted for any type, is call methods.
-
-However, method calls are not sufficient for everything we want to
-express.
-Consider this simple function that returns the smallest element of a
-slice of values, where the slice is assumed to be non-empty.
-
-```
-// This function is INVALID.
-func Smallest[T any](s []T) T {
-	r := s[0] // panic if slice is empty
-	for _, v := range s[1:] {
-		if v < r { // INVALID
-			r = v
-		}
-	}
-	return r
-}
-```
-
-Any reasonable generics implementation should let you write this
-function.
-The problem is the expression `v < r`.
-This assumes that `T` supports the `<` operator, but the constraint on
-`T` is simply `any`.
-With the `any` constraint the function `Smallest` can only use
-operations that are available for all types, but not all Go types
-support `<`.
-Unfortunately, since `<` is not a method, there is no obvious way to
-write a constraint&mdash;an interface type&mdash;that permits `<`.
-
-We need a way to write a constraint that accepts only types that
-support `<`.
-In order to do that, we observe that, aside from two exceptions that
-we will discuss later, all the arithmetic, comparison, and logical
-operators defined by the language may only be used with types that are
-predeclared by the language, or with defined types whose underlying
-type is one of those predeclared types.
-That is, the operator `<` can only be used with a predeclared type
-such as `int` or `float64`, or a defined type whose underlying type is
-one of those types.
-Go does not permit using `<` with a composite type or with an
-arbitrary defined type.
-
-This means that rather than try to write a constraint for `<`, we can
-approach this the other way around: instead of saying which operators
-a constraint should support, we can say which (underlying) types a
-constraint should accept.
-
-#### Type lists in constraints
-
-An interface type used as a constraint may list explicit types that
-may be used as type arguments.
-This is done using the `type` keyword followed by a comma-separated
-list of types.
-
-For example:
-
-```
-// SignedInteger is a type constraint that permits any
-// signed integer type.
-type SignedInteger interface {
-	type int, int8, int16, int32, int64
-}
-```
-
-The `SignedInteger` constraint specifies that the type argument
-must be one of the listed types.
-More precisely, either the type argument or the underlying type of the
-type argument must be identical to one of the types in the type list.
-This means that `SignedInteger` will accept the listed integer types,
-and will also accept any type that is defined as one of those types.
-
-When a generic function uses a type parameter with one of these
-constraints, it may use it in any way that is permitted by all of the
-listed types.
-This could mean operators like `<`, `<-`, or use in a `range` loop, or
-in general any language construct.
-If the function can be compiled successfully using each type listed in
-the constraint, then the use is permitted.
-
-A constraint may only have one type list.
-
-For the `Smallest` example shown earlier, we could use a constraint
-like this:
-
-```
-package constraints
-
-// Ordered is a type constraint that matches any ordered type.
-// An ordered type is one that supports the <, <=, >, and >= operators.
-type Ordered interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr,
-		float32, float64,
-		string
-}
-```
-
-In practice this constraint would likely be defined and exported in a
-new standard library package, `constraints`, so that it could be used
-by function and type definitions.
-
-Given that constraint, we can write this function, now valid:
-
-```
-// Smallest returns the smallest element in a slice.
-// It panics if the slice is empty.
-func Smallest[T constraints.Ordered](s []T) T {
-	r := s[0] // panics if slice is empty
-	for _, v := range s[1:] {
-		if v < r {
-			r = v
-		}
-	}
-	return r
-}
-```
-
-#### Comparable types in constraints
-
-Earlier we mentioned that there are two exceptions to the rule that
-operators may only be used with types that are predeclared by the
-language.
-The exceptions are `==` and `!=`, which are permitted for struct,
-array, and interface types.
-These are useful enough that we want to be able to write a constraint
-that accepts any comparable type.
-
-To do this we introduce a new predeclared type constraint:
-`comparable`.
-A type parameter with the `comparable` constraint accepts as a type
-argument any comparable type.
-It permits the use of `==` and `!=` with values of that type parameter.
-
-For example, this function may be instantiated with any comparable
-type:
-
-```
-// Index returns the index of x in s, or -1 if not found.
-func Index[T comparable](s []T, x T) int {
-	for i, v := range s {
-		// v and x are type T, which has the comparable
-		// constraint, so we can use == here.
-		if v == x {
-			return i
-		}
-	}
-	return -1
-}
-```
-
-Since `comparable`, like all constraints, is an interface type, it can
-be embedded in another interface type used as a constraint:
-
-```
-// ComparableHasher is a type constraint that matches all
-// comparable types with a Hash method.
-type ComparableHasher interface {
-	comparable
-	Hash() uintptr
-}
-```
-
-The constraint `ComparableHasher` is implemented by any type that is
-comparable and also has a `Hash() uintptr` method.
-A generic function that uses `ComparableHasher` as a constraint can
-compare values of that type and can call the `Hash` method.
-
-It's possible to use `comparable` to produce a constraint that can not
-be satisfied by any type.
-
-```
-// ImpossibleConstraint is a type constraint that no type can satisfy,
-// because slice types are not comparable.
-type ImpossibleConstraint interface {
-	comparable
-	type []int
-}
-```
-
-This is not in itself an error, but of course there is no way to
-instantiate a type parameter that uses such a constraint.
-
-#### Type lists in interface types
-
-Interface types with type lists may only be used as constraints on
-type parameters.
-They may not be used as ordinary interface types.
-The same is true of the predeclared interface type `comparable`.
-
-This restriction may be lifted in future language versions.
-An interface type with a type list may be useful as a form of sum
-type, albeit one that can have the value `nil`.
-
-A type argument satisfies a type constraint with a type list if the
-type argument or its underlying type is present in that type list.
-If in some future language version we permit interface types with type
-lists outside of type constraints, this rule will make them usable
-both as type constraints and as sum types.
-Using a list of defined types would mean that only those exact types
-would implement the interface, which is to say that only those exact
-types could be assigned to the sum type.
-Using a list of predeclared types and/or type literals would mean that
-any type defined as one of those types would implement the interface
-or be assignable to the sum type.
-There would be no way to write a sum type to accept only a predeclared
-type or type literal and reject types defined as those types.
-That restriction is likely acceptable for the cases where people want
-to use sum types.
-
-### Mutually referencing type parameters
-
-Within a single type parameter list, constraints may refer to any of
-the other type parameters, even ones that are declared later in the
-same list.
-(The scope of a type parameter starts at the beginning of the type
-parameter list and extends to the end of the enclosing function or
-type declaration.)
-
-For example, consider a generic graph package that contains generic
-algorithms that work with graphs.
-The algorithms use two types, `Node` and `Edge`.
-`Node` is expected to have a method `Edges() []Edge`.
-`Edge` is expected to have a method `Nodes() (Node, Node)`.
-A graph can be represented as a `[]Node`.
-
-This simple representation is enough to implement graph algorithms
-like finding the shortest path.
-
-```
-package graph
-
-// NodeConstraint is the type constraint for graph nodes:
-// they must have an Edges method that returns the Edge's
-// that connect to this Node.
-type NodeConstraint[Edge any] interface {
-	Edges() []Edge
-}
-
-// EdgeConstraint is the type constraint for graph edges:
-// they must have a Nodes method that returns the two Nodes
-// that this edge connects.
-type EdgeConstraint[Node any] interface {
-	Nodes() (from, to Node)
-}
-
-// Graph is a graph composed of nodes and edges.
-type Graph[Node NodeConstraint[Edge], Edge EdgeConstraint[Node]] struct { ... }
-
-// New returns a new graph given a list of nodes.
-func New[Node NodeConstraint[Edge], Edge EdgeConstraint[Node]] (nodes []Node) *Graph[Node, Edge] {
-	...
-}
-
-// ShortestPath returns the shortest path between two nodes,
-// as a list of edges.
-func (g *Graph[Node, Edge]) ShortestPath(from, to Node) []Edge { ... }
-```
-
-There are a lot of type arguments and instantiations here.
-In the constraint on `Node` in `Graph`, the `Edge` being passed to the
-type constraint `NodeConstraint` is the second type parameter of
-`Graph`.
-This instantiates `NodeConstraint` with the type parameter `Edge`, so
-we see that `Node` must have a method `Edges` that returns a slice of
-`Edge`, which is what we want.
-The same applies to the constraint on `Edge`, and the same type
-parameters and constraints are repeated for the function `New`.
-We aren't claiming that this is simple, but we are claiming that it is
-possible.
-
-It's worth noting that while at first glance this may look like a
-typical use of interface types, `Node` and `Edge` are non-interface
-types with specific methods.
-In order to use `graph.Graph`, the type arguments used for `Node` and
-`Edge` have to define methods that follow a certain pattern, but they
-don't have to actually use interface types to do so.
-In particular, the methods do not return interface types.
-
-For example, consider these type definitions in some other package:
-
-```
-// Vertex is a node in a graph.
-type Vertex struct { ... }
-
-// Edges returns the edges connected to v.
-func (v *Vertex) Edges() []*FromTo { ... }
-
-// FromTo is an edge in a graph.
-type FromTo struct { ... }
-
-// Nodes returns the nodes that ft connects.
-func (ft *FromTo) Nodes() (*Vertex, *Vertex) { ... }
-```
-
-There are no interface types here, but we can instantiate
-`graph.Graph` using the type arguments `*Vertex` and `*FromTo`.
-
-```
-var g = graph.New[*Vertex, *FromTo]([]*Vertex{ ... })
-```
-
-`*Vertex` and `*FromTo` are not interface types, but when used
-together they define methods that implement the constraints of
-`graph.Graph`.
-Note that we couldn't pass plain `Vertex` or `FromTo` to `graph.New`,
-since `Vertex` and `FromTo` do not implement the constraints.
-The `Edges` and `Nodes` methods are defined on the pointer types
-`*Vertex` and `*FromTo`; the types `Vertex` and `FromTo` do not have
-any methods.
-
-When we use a generic interface type as a constraint, we first
-instantiate the type with the type argument(s) supplied in the type
-parameter list, and then compare the corresponding type argument
-against the instantiated constraint.
-In this example, the `Node` type argument to `graph.New` has a
-constraint `NodeConstraint[Edge]`.
-When we call `graph.New` with a `Node` type argument of `*Vertex` and
-an `Edge` type argument of `*FromTo`, in order to check the constraint
-on `Node` the compiler instantiates `NodeConstraint` with the type
-argument `*FromTo`.
-That produces an instantiated constraint, in this case a requirement
-that `Node` have a method `Edges() []*FromTo`, and the compiler
-verifies that `*Vertex` satisfies that constraint.
-
-Although `Node` and `Edge` do not have to be instantiated with
-interface types, it is also OK to use interface types if you like.
-
-```
-type NodeInterface interface { Edges() []EdgeInterface }
-type EdgeInterface interface { Nodes() (NodeInterface, NodeInterface) }
-```
-
-We could instantiate `graph.Graph` with the types `NodeInterface` and
-`EdgeInterface`, since they implement the type constraints.
-There isn't much reason to instantiate a type this way, but it is
-permitted.
-
-This ability for type parameters to refer to other type parameters
-illustrates an important point: it should be a requirement for any
-attempt to add generics to Go that it be possible to instantiate
-generic code with multiple type arguments that refer to each other in
-ways that the compiler can check.
-
-### Type inference
-
-In many cases we can use type inference to avoid having to explicitly
-write out some or all of the type arguments.
-We can use _function argument type inference_ for a function call to
-deduce type arguments from the types of the non-type arguments.
-We can use _constraint type inference_ to deduce unknown type arguments
-from known type arguments.
-
-In the examples above, when instantiating a generic function or type,
-we always specified type arguments for all the type parameters.
-We also permit specifying just some of the type arguments, or omitting
-the type arguments entirely, when the missing type arguments can be
-inferred.
-When only some type arguments are passed, they are the arguments for
-the first type parameters in the list.
-
-For example, a function like this:
-
-```
-func Map[F, T any](s []F, f func(F) T) []T { ... }
-```
-
-can be called in these ways.  (We'll explain below how type inference
-works in detail; this example is to show how an incomplete list of
-type arguments is handled.)
-
-```
-	var s []int
-	f := func(i int) int64 { return int64(i) }
-	var r []int64
-	// Specify both type arguments explicitly.
-	r = Map[int, int64](s, f)
-	// Specify just the first type argument, for F,
-	// and let T be inferred.
-	r = Map[int](s, f)
-	// Don't specify any type arguments, and let both be inferred.
-	r = Map(s, f)
-```
-
-If a generic function or type is used without specifying all the type
-arguments, it is an error if any of the unspecified type arguments
-cannot be inferred.
-
-(Note: type inference is a convenience feature.
-Although we think it is an important feature, it does not add any
-functionality to the design, only convenience in using it.
-It would be possible to omit it from the initial implementation, and
-see whether it seems to be needed.
-That said, this feature doesn't require additional syntax, and
-produces more readable code.)
-
-#### Type unification
-
-Type inference is based on _type unification_.
-Type unification applies to two types, either or both of which may be
-or contain type parameters.
-
-Type unification works by comparing the structure of the types.
-Their structure disregarding type parameters must be identical, and
-types other than type parameters must be equivalent.
-A type parameter in one type may match any complete subtype in the
-other type.
-If the structure differs, or types other than type parameters are not
-equivalent, then type unification fails.
-A successful type unification provides a list of associations of type
-parameters with other types (which may themselves be or contain type
-parameters).
-
-For type unification, two types that don't contain any type parameters
-are equivalent if they are
-[identical](https://golang.org/ref/spec#Type_identity), or if they are
-channel types that are identical ignoring channel direction, or if
-their underlying types are equivalent.
-It's OK to permit types to not be identical during type inference,
-because we will still check the constraints if inference succeeds, and
-we will still check that the function arguments are assignable to the
-inferred types.
-
-For example, if `T1` and `T2` are type parameters, `[]map[int]bool`
-can be unified with any of the following:
-  * `[]map[int]bool`
-  * `T1` (`T1` matches `[]map[int]bool`)
-  * `[]T1` (`T1` matches `map[int]bool`)
-  * `[]map[T1]T2` (`T1` matches `int`, `T2` matches `bool`)
-
-(This is not an exclusive list, there are other possible successful
-unifications.)
-
-On the other hand, `[]map[int]bool` cannot be unified with any of
-  * `int`
-  * `struct{}`
-  * `[]struct{}`
-  * `[]map[T1]string`
-
-(This list is of course also not exclusive; there are an infinite
-number of types that cannot be successfully unified.)
-
-In general we can also have type parameters on both sides, so in some
-cases we might associate `T1` with, for example, `T2`, or `[]T2`.
-
-#### Function argument type inference
-
-Function argument type inference is used with a function call to infer
-type arguments from non-type arguments.
-Function argument type inference is not used when a type is
-instantiated, and it is not used when a function is instantiated but
-not called.
-
-To see how it works, let's go back to [the example](#Type-parameters)
-of a call to the simple `Print` function:
-
-```
-	Print[int]([]int{1, 2, 3})
-```
-
-The type argument `int` in this function call can be inferred from the
-type of the non-type argument.
-
-The only type arguments that can be inferred are those that are used
-for the types of the function's (non-type) input parameters.
-If there are some type parameters that are used only for the
-function's result parameter types, or only in the body of the
-function, then those type arguments cannot be inferred using function
-argument type inference.
-
-To infer function type arguments, we unify the types of the function
-call arguments with the types of the function's non-type parameters.
-On the caller side we have the list of types of the actual (non-type)
-arguments, which for the `Print` example is simply `[]int`.
-On the function side is the list of the types of the function's
-non-type parameters, which for `Print` is `[]T`.
-In the lists, we discard respective arguments for which the function
-side does not use a type parameter.
-We must then apply type unification to the remaining argument types.
-
-Function argument type inference is a two-pass algorithm.
-In the first pass, we ignore untyped constants on the caller side and
-their corresponding types in the function definition.
-We use two passes so that in some cases later arguments can determine
-the type of an untyped constant.
-
-We unify corresponding types in the lists.
-This will give us an association of type parameters on the function
-side to types on the caller side.
-If the same type parameter appears more than once on the function
-side, it will match multiple argument types on the caller side.
-If those caller types are not equivalent, we report an error.
-
-After the first pass, we check any untyped constants on the caller
-side.
-If there are no untyped constants, or if the type parameters in the
-corresponding function types have matched other input types, then
-type unification is complete.
-
-Otherwise, for the second pass, for any untyped constants whose
-corresponding function types are not yet set, we determine the default
-type of the untyped constant in [the usual
-way](https://golang.org/ref/spec#Constants).
-Then we unify the remaining types again, this time with no untyped
-constants.
-
-In this example
-
-```
-	s1 := []int{1, 2, 3}
-	Print(s1)
-```
-
-we compare `[]int` with `[]T`, match `T` with `int`, and we are done.
-The single type parameter `T` is `int`, so we infer that the call to
-`Print` is really a call to `Print[int]`.
-
-For a more complex example, consider
-
-```
-// Map calls the function f on every element of the slice s,
-// returning a new slice of the results.
-func Map[F, T any](s []F, f func(F) T) []T {
-	r := make([]T, len(s))
-	for i, v := range s {
-		r[i] = f(v)
-	}
-	return r
-}
-```
-
-The two type parameters `F` and `T` are both used for input
-parameters, so function argument type inference is possible.
-In the call
-
-```
-	strs := Map([]int{1, 2, 3}, strconv.Itoa)
-```
-
-we unify `[]int` with `[]F`, matching `F` with `int`.
-We unify the type of `strconv.Itoa`, which is `func(int) string`,
-with `func(F) T`, matching `F` with `int` and `T` with `string`.
-The type parameter `F` is matched twice, both times with `int`.
-Unification succeeds, so the call written as `Map` is a call of
-`Map[int, string]`.
-
-To see the untyped constant rule in effect, consider:
-
-```
-// NewPair returns a pair of values of the same type.
-func NewPair[F any](f1, f2 F) *Pair[F] { ... }
-```
-
-In the call `NewPair(1, 2)` both arguments are untyped constants, so
-both are ignored in the first pass.
-There is nothing to unify.
-We still have two untyped constants after the first pass.
-Both are set to their default type, `int`.
-The second run of the type unification pass unifies `F` with
-`int`, so the final call is `NewPair[int](1, 2)`.
-
-In the call `NewPair(1, int64(2))` the first argument is an untyped
-constant, so we ignore it in the first pass.
-We then unify `int64` with `F`.
-At this point the type parameter corresponding to the untyped constant
-is fully determined, so the final call is `NewPair[int64](1,
-int64(2))`.
-
-In the call `NewPair(1, 2.5)` both arguments are untyped constants,
-so we move on the second pass.
-This time we set the first constant to `int` and the second to
-`float64`.
-We then try to unify `F` with both `int` and `float64`, so unification
-fails, and we report a compilation error.
-
-As mentioned earlier, function argument type inference is done without
-regard to constraints.
-First we use function argument type inference to determine type
-arguments to use for the function, and then, if that succeeds, we
-check whether those type arguments implement the constraints (if
-any).
-
-Note that after successful function argument type inference, the
-compiler must still check that the arguments can be assigned to the
-parameters, as for any function call.
-
-#### Constraint type inference
-
-Constraint type inference permits inferring a type argument from
-another type argument, based on type parameter constraints.
-Constraint type inference is useful when a function wants to have a
-type name for an element of some other type parameter, or when a
-function wants to apply a constraint to a type that is based on some
-other type parameter.
-
-Constraint type inference can only infer types if some type parameter
-has a constraint that has a type list with exactly one type in it.
-We call such a constraint a _structural constraint_, as the type list
-describes the structure of the type parameter.
-A structural constraint may also have methods in addition to the type
-list, but the methods are ignored by constraint type inference.
-For constraint type inference to be useful, the constraint type will
-normally refer to one or more type parameters.
-
-Constraint type inference is applied after function argument type
-inference.
-It is only tried if there is at least one type parameter whose type
-argument is not yet known.
-
-While the algorithm we describe here may seem complex, for typical
-concrete examples it is straightforward to see what constraint type
-inference will deduce.
-The description of the algorithm is followed by a couple of examples.
-
-We start by creating a mapping from type parameters to type arguments.
-We initialize the mapping with all type parameters whose type
-arguments are already known, if any.
-
-For each type parameter with a structural constraint, we unify the
-type parameter with the single type in the constraint's type list.
-This will have the effect of associating the type parameter with its
-constraint.
-We add the result into the mapping we are maintaining.
-If unification finds any associations of type parameters, we add those
-to the mapping as well.
-When we find multiple associations of any one type parameter, we unify
-each such association to produce a single mapping entry.
-If a type parameter is associated directly with another type
-parameter, meaning that they must both be matched with the same type,
-we unify the associations of each parameter together.
-If any of these various unifications fail, then constraint type
-inference fails.
-
-After merging all type parameters with structural constraints, we have
-a mapping of various type parameters to types (which may be or contain
-other type parameters).
-We continue by looking for a type parameter `T` that is mapped to a
-fully known type argument `A`, one that does not contain any type
-parameters.
-Anywhere that `T` appears in a type argument in the mapping, we
-replace `T` with `A`.
-We repeat this process until we have replaced every type parameter.
-
-##### Element constraint example
-
-For an example of where constraint type inference is useful, let's
-consider a function that takes a defined type that is a slice of
-numbers, and returns an instance of that same defined type in which
-each number is doubled.
-
-Using type lists, it's easy to write a function similar to this if we
-ignore the [defined
-type](https://golang.org/ref/spec#Type_definitions) requirement.
-
-```
-// Double returns a new slice that contains all the elements of s, doubled.
-func Double[E constraints.Number](s []E) []E {
-	r := make([]E, len(s))
-	for i, v := range s {
-		r[i] = v + v
-	}
-	return r
-}
-```
-
-However, with that definition, if we call the function with a defined
-slice type, the result will not be that defined type.
-
-```
-// MySlice is a slice of ints.
-type MySlice []int
-
-// The type of V1 will be []int, not MySlice.
-// Here we are using function argument type inference,
-// but not constraint type inference.
-var V1 = Double(MySlice{1})
-```
-
-We can do what we want by introducing a new type parameter.
-
-```
-// SC constraints a type to be a slice of some type E.
-type SC[E any] interface {
-	type []E
-}
-
-// DoubleDefined returns a new slice that contains the elements of s,
-// doubled, and also has the same type as s.
-func DoubleDefined[S SC[E], E constraints.Number](s S) S {
-	// Note that here we pass S to make, where above we passed []E.
-	r := make(S, len(s))
-	for i, v := range s {
-		r[i] = v + v
-	}
-	return r
-}
-```
-
-Now if we use explicit type arguments, we can get the right type.
-
-```
-// The type of V2 will be MySlice.
-var V2 = DoubleDefined[MySlice, int](MySlice{1})
-```
-
-Function argument type inference by itself is not enough to infer the
-type arguments here, because the type parameter E is not used for any
-input parameter.
-But a combination of function argument type inference and constraint
-type inference works.
-
-```
-// The type of V3 will be MySlice.
-var V3 = DoubleDefined(MySlice{1})
-```
-
-First we apply function argument type inference.
-We see that the type of the argument is `MySlice`.
-Function argument type inference matches the type parameter `S` with
-`MySlice`.
-
-We then move on to constraint type inference.
-We know one type argument, `S`.
-We see that the type argument `S` has a structural type constraint.
-
-We create a mapping of known type arguments:
-
-```
-{S -> MySlice}
-```
-
-We then unify each type parameter with a structural constraint with
-the single type listed by that constraint.
-In this case the structural constraint is `SC[E]` which has the single
-type `[]E`, so we unify `S` with `[]E`.
-Since we already have a mapping for `S`, we then unify `[]E` with
-`MySlice`.
-As `MySlice` is defined as `[]int`, that associates `E` with `int`.
-We now have:
-
-```
-{S -> MySlice, E -> int}
-```
-
-We then substitute `E` with `int`, which changes nothing, and we are
-done.
-The type arguments for this call to `DoubleDefined` are `[MySlice,
-int]`.
-
-This example shows how we can use constraint type inference to set a
-type name for an element of some other type parameter.
-In this case we can name the element type of `S` as `E`, and we can
-then apply further constraints to `E`, in this case requiring that it
-be a number.
-
-##### Pointer method example
-
-Consider this example of a function that expects a type `T` that has a
-`Set(string)` method that initializes a value based on a string.
-
-```
-// Setter is a type constraint that requires that the type
-// implement a Set method that sets the value from a string.
-type Setter interface {
-	Set(string)
-}
-
-// FromStrings takes a slice of strings and returns a slice of T,
-// calling the Set method to set each returned value.
-//
-// Note that because T is only used for a result parameter,
-// function argument type inference does not work when calling
-// this function.
-func FromStrings[T Setter](s []string) []T {
-	result := make([]T, len(s))
-	for i, v := range s {
-		result[i].Set(v)
-	}
-	return result
-}
-```
-
-Now let's see some calling code (this example is invalid).
-
-```
-// Settable is an integer type that can be set from a string.
-type Settable int
-
-// Set sets the value of *p from a string.
-func (p *Settable) Set(s string) {
-	i, _ := strconv.Atoi(s) // real code should not ignore the error
-	*p = Settable(i)
-}
-
-func F() {
-	// INVALID
-	nums := FromStrings[Settable]([]string{"1", "2"})
-	// Here we want nums to be []Settable{1, 2}.
-	...
-}
-```
-
-The goal is to use `FromStrings` to get a slice of type `[]Settable`.
-Unfortunately, this example is not valid and will not compile.
-
-The problem is that `FromStrings` requires a type that has a
-`Set(string)` method.
-The function `F` is trying to instantiate `FromStrings` with
-`Settable`, but `Settable` does not have a `Set` method.
-The type that has a `Set` method is `*Settable`.
-
-So let's rewrite `F` to use `*Settable` instead.
-
-```
-func F() {
-	// Compiles but does not work as desired.
-	// This will panic at run time when calling the Set method.
-	nums := FromStrings[*Settable]([]string{"1", "2"})
-	...
-}
-```
-
-This compiles but unfortunately it will panic at run time.
-The problem is that `FromStrings` creates a slice of type `[]T`.
-When instantiated with `*Settable`, that means a slice of type
-`[]*Settable`.
-When `FromStrings` calls `result[i].Set(v)`, that invokes the `Set`
-method on the pointer stored in `result[i]`.
-That pointer is `nil`.
-The `Settable.Set` method will be invoked with a `nil` receiver, and
-will raise a panic due to a `nil` dereference error.
-
-The pointer type `*Settable` implements the constraint, but the code
-really wants to use the non-pointer type`Settable`.
-What we need is a way to write `FromStrings` such that it can take the
-type `Settable` as an argument but invoke a pointer method.
-To repeat, we can't use `Settable` because it doesn't have a `Set`
-method, and we can't use `*Settable` because then we can't create a
-slice of type `Settable`.
-
-What we can do is pass both types.
-
-```
-// Setter2 is a type constraint that requires that the type
-// implement a Set method that sets the value from a string,
-// and also requires that the type be a pointer to its type parameter.
-type Setter2[B any] interface {
-	Set(string)
-	type *B
-}
-
-// FromStrings2 takes a slice of strings and returns a slice of T,
-// calling the Set method to set each returned value.
-//
-// We use two different type parameters so that we can return
-// a slice of type T but call methods on *T aka PT.
-// The Setter2 constraint ensures that PT is a pointer to T.
-func FromStrings2[T any, PT Setter2[T]](s []string) []T {
-	result := make([]T, len(s))
-	for i, v := range s {
-		// The type of &result[i] is *T which is in the type list
-		// of Setter2, so we can convert it to PT.
-		p := PT(&result[i])
-		// PT has a Set method.
-		p.Set(v)
-	}
-	return result
-}
-```
-
-We can then call `FromStrings2` like this:
-
-```
-func F2() {
-	// FromStrings2 takes two type parameters.
-	// The second parameter must be a pointer to the first.
-	// Settable is as above.
-	nums := FromStrings2[Settable, *Settable]([]string{"1", "2"})
-	// Now nums is []Settable{1, 2}.
-	...
-}
-```
-
-This approach works as expected, but it is awkward to have to repeat
-`Settable` in the type arguments.
-Fortunately, constraint type inference makes it less awkward.
-Using constraint type inference we can write
-
-```
-func F3() {
-	// Here we just pass one type argument.
-	nums := FromStrings2[Settable]([]string{"1", "2"})
-	// Now nums is []Settable{1, 2}.
-	...
-}
-```
-
-There is no way to avoid passing the type argument `Settable`.
-But given that type argument, constraint type inference can infer the
-type argument `*Settable` for the type parameter `PT`.
-
-As before, we create a mapping of known type arguments:
-
-```
-{T -> Settable}
-```
-
-We then unify each type parameter with a structural constraint.
-In this case, we unify `PT` with the single type of `Setter2[T]`,
-which is `*T`.
-The mapping is now
-
-```
-{T -> Settable, PT -> *T}
-```
-
-We then replace `T` with `Settable` throughout, giving us:
-
-```
-{T -> Settable, PT -> *Settable}
-```
-
-After this nothing changes, and we are done.
-Both type arguments are known.
-
-This example shows how we can use constraint type inference to apply a
-constraint to a type that is based on some other type parameter.
-In this case we are saying that `PT`, which is `*T`, must have a `Set`
-method.
-We can do this without requiring the caller to explicitly mention
-`*T`.
-
-##### Constraints apply even after constraint type inference
-
-Even when constraint type inference is used to infer type arguments
-based on constraints, we must still check the constraints after the
-type arguments are determined.
-
-In the `FromStrings2` example above, we were able to deduce the type
-argument for `PT` based on the `Setter2` constraint.
-But in doing so we only looked at the type list, we didn't look at the
-methods.
-We still have to verify that the method is there, satisfying the
-constraint, even if constraint type inference succeeds.
-
-For example, consider this invalid code:
-
-```
-// Unsettable is a type that does not have a Set method.
-type Unsettable int
-
-func F4() {
-	// This call is INVALID.
-	nums := FromString2[Unsettable]([]string{"1", "2"})
-	...
-}
-```
-
-When this call is made, we will apply constraint type inference just
-as before.
-It will succeed, just as before, and infer that the type arguments are
-`[Unsettable, *Unsettable]`.
-Only after constraint type inference is complete will we check whether
-`*Unsettable` implements the constraint `Setter2[Unsettable]`.
-Since `*Unsettable` does not have a `Set` method, constraint checking
-will fail, and this code will not compile.
-
-### Using types that refer to themselves in constraints
-
-It can be useful for a generic function to require a type argument
-with a method whose argument is the type itself.
-For example, this arises naturally in comparison methods.
-(Note that we are talking about methods here, not operators.)
-Suppose we want to write an `Index` method that uses an `Equal` method
-to check whether it has found the desired value.
-We would like to write that like this:
-
-```
-// Index returns the index of e in s, or -1 if not found.
-func Index[T Equaler](s []T, e T) int {
-	for i, v := range s {
-		if e.Equal(v) {
-			return i
-		}
-	}
-	return -1
-}
-```
-
-In order to write the `Equaler` constraint, we have to write a
-constraint that can refer to the type argument being passed in.
-The easiest way to do this is to take advantage of the fact that a
-constraint does not have to be a defined type, it can simply be an
-interface type literal.
-This interface type literal can then refer to the type parameter.
-
-```
-// Index returns the index of e in s, or -1 if not found.
-func Index[T interface { Equal(T) bool }](s []T, e T) int {
-	// same as above
-}
-```
-
-This version of `Index` would be used with a type like `equalInt`
-defined here:
-
-```
-// equalInt is a version of int that implements Equaler.
-type equalInt int
-
-// The Equal method lets equalInt implement the Equaler constraint.
-func (a equalInt) Equal(b equalInt) bool { return a == b }
-
-// indexEqualInts returns the index of e in s, or -1 if not found.
-func indexEqualInt(s []equalInt, e equalInt) int {
-	// The type argument equalInt is shown here for clarity.
-	// Function argument type inference would permit omitting it.
-	return Index[equalInt](s, e)
-}
-```
-
-In this example, when we pass `equalInt` to `Index`, we check whether
-`equalInt` implements the constraint `interface { Equal(T) bool }`.
-The constraint has a type parameter, so we replace the type parameter
-with the type argument, which is `equalInt` itself.
-That gives us `interface { Equal(equalInt) bool }`.
-The `equalInt` type has an `Equal` method with that signature, so all
-is well, and the compilation succeeds.
-
-### Values of type parameters are not boxed
-
-In the current implementations of Go, interface values always hold
-pointers.
-Putting a non-pointer value in an interface variable causes the value
-to be _boxed_.
-That means that the actual value is stored somewhere else, on the heap
-or stack, and the interface value holds a pointer to that location.
-
-In this design, values of generic types are not boxed.
-For example, let's look back at our earlier example of
-`FromStrings2`.
-When it is instantiated with type `Settable`, it returns a value of
-type `[]Settable`.
-For example, we can write
-
-```
-// Settable is an integer type that can be set from a string.
-type Settable int
-
-// Set sets the value of *p from a string.
-func (p *Settable) Set(s string) {
-	// same as above
-}
-
-func F() {
-	// The type of nums is []Settable.
-	nums := FromStrings2[Settable]([]string{"1", "2"})
-	// Settable can be converted directly to int.
-	// This will set first to 1.
-	first := int(nums[0])
-	...
-}
-```
-
-When we call `FromStrings2` instantiated with the type `Settable` we
-get back a `[]Settable`.
-The elements of that slice will be `Settable` values, which is to say,
-they will be integers.
-They will not be boxed, even though they were created and set by a
-generic function.
-
-Similarly, when a generic type is instantiated it will have the
-expected types as components.
-
-```
-type Pair[F1, F2 any] struct {
-	first  F1
-	second F2
-}
-```
-
-When this is instantiated, the fields will not be boxed, and no
-unexpected memory allocations will occur.
-The type `Pair[int, string]` is convertible to `struct { first int;
-second string }`.
-
-### More on type lists
-
-Let's return now to type lists to cover some less important details
-that are still worth noting.
-These are not additional rules or concepts, but are consequences of
-how type lists work.
-
-#### Both type lists and methods in constraints
-
-As seen earlier for `Setter2`, a constraint may use both type lists
-and methods.
-
-```
-// StringableSignedInteger is a type constraint that matches any
-// type that is both 1) defined as a signed integer type;
-// 2) has a String method.
-type StringableSignedInteger interface {
-	type int, int8, int16, int32, int64
-	String() string
-}
-```
-
-This constraint permits any type whose underlying type is one of the
-listed types, provided it also has a `String() string` method.
-It's worth noting that although the `StringableSignedInteger`
-constraint explicitly lists `int`, the type `int` will not itself be
-permitted as a type argument, since `int` does not have a `String`
-method.
-An example of a type argument that would be permitted is `MyInt`,
-defined as:
-
-```
-// MyInt is a stringable int.
-type MyInt int
-
-// The String method returns a string representation of mi.
-func (mi MyInt) String() string {
-	return fmt.Sprintf("MyInt(%d)", mi)
-}
-```
-
-#### Types with methods in type lists
-
-Using a type list permits a generic function to use an operation that
-is permitted by all the types in the type list.
-However, that does not apply to methods.
-Even if every type in the type list supports the same method with the
-same signature, the generic function may not call that method.
-It may only call methods that are explicitly listed in the constraint,
-as explained in the previous section.
-
-Here is an example of types with the same method.
-This example is invalid.
-Even though both `MyInt` and `MyFloat` have a `String` method, the
-`ToString` function is not permitted to call that method.
-
-```
-// MyInt has a String method.
-type MyInt int
-
-func (i MyInt) String() string {
-	return strconv.Itoa(int(i))
-}
-
-// MyFloat also has a String method.
-type MyFloat float64
-
-func (f MyFloat) String() string {
-	return strconv.FormatFloat(float64(f), 'g', -1, 64)
-}
-
-// MyIntOrFloat is a type constraint that accepts MyInt or MyFloat.
-type MyIntOrFloat interface {
-	type MyInt, MyFloat
-}
-
-// ToString converts a value to a string.
-// This function is INVALID.
-func ToString[T MyIntOrFloat](v T) string {
-	return v.String() // INVALID
-}
-```
-
-To permit the `String` method to be called, it must be explicitly
-listed in the constraint.
-
-```
-// MyIntOrFloatStringer accepts MyInt or MyFloat, and defines a String
-// method. Note that both MyInt and MyFloat have a String method.
-// If either did not have a String method, they would not satisfy the
-// constraint even though the type list lists them. To satisfy a
-// constraint a type must both match the type list (if any) and
-// implement all the methods (if any).
-type MyIntOrFloatStringer interface {
-	type MyInt, MyFloat
-	String() string
-}
-
-// ToString2 convers a value to a string.
-func ToString2[T MyIntOrFloatStringer](v T) string {
-	return v.String()
-}
-```
-
-The reason for this rule is to simplify complex cases involving
-embedded type parameters in which it may not be immediately clear
-whether the type has a particular method or not.
-
-#### Composite types in constraints
-
-A type in a constraint may be a type literal.
-
-```
-type byteseq interface {
-	type string, []byte
-}
-```
-
-The usual rules apply: the type argument for this constraint may be
-`string` or `[]byte` or a type defined as one of those types; a
-generic function with this constraint may use any operation permitted
-by both `string` and `[]byte`.
-
-The `byteseq` constraint permits writing generic functions that work
-for either `string` or `[]byte` types.
-
-```
-// Join concatenates the elements of its first argument to create a
-// single value. sep is placed between elements in the result.
-// Join works for string and []byte types.
-func Join[T byteseq](a []T, sep T) (ret T) {
-	if len(a) == 0 {
-		// Use the result parameter as a zero value;
-		// see discussion of zero value in the Issues section.
-		return ret
-	}
-	if len(a) == 1 {
-		// We know that a[0] is either a string or a []byte.
-		// We can append either a string or a []byte to a []byte,
-		// producing a []byte. We can convert that []byte to
-		// either a []byte (a no-op conversion) or a string.
-		return T(append([]byte(nil), a[0]...))
-	}
-	// We can call len on sep because we can call len
-	// on both string and []byte.
-	n := len(sep) * (len(a) - 1)
-	for _, v := range a {
-		// Another case where we call len on string or []byte.
-		n += len(v)
-	}
-
-	b := make([]byte, n)
-	// We can call copy to a []byte with an argument of
-	// either string or []byte.
-	bp := copy(b, a[0])
-	for _, s := range a[1:] {
-		bp += copy(b[bp:], sep)
-		bp += copy(b[bp:], s)
-	}
-	// As above, we can convert b to either []byte or string.
-	return T(b)
-}
-```
-
-For composite types (string, pointer, array, slice, struct, function,
-map, channel) we impose an additional restriction: an operation may
-only be used if the operator accepts identical input types (if any)
-and produces identical result types for all of the types listed in the
-type list.
-To be clear, this additional restriction is only imposed when a
-composite type appears in a type list.
-It does not apply when a composite type is formed from a type
-parameter outside of a type list, as in `var v []T` for some type
-parameter `T`.
-
-```
-// structField is a type constraint with a list of structs that all
-// have a field named x.
-type structField interface {
-	type struct { a int; x int },
-		struct { b int; x float64 },
-		struct { c int; x uint64 }
-}
-
-// This function is INVALID.
-func IncrementX[T structField](p *T) {
-	v := p.x // INVALID: type of p.x is not the same for all types in list
-	v++
-	p.x = v
-}
-
-// sliceOrMap is a type constraint for a slice or a map.
-type sliceOrMap interface {
-	type []int, map[int]int
-}
-
-// Entry returns the i'th entry in a slice or the value of a map
-// at key i. This is valid as the result of the operator is always int.
-func Entry[T sliceOrMap](c T, i int) int {
-	// This is either a slice index operation or a map key lookup.
-	// Either way, the index and result types are type int.
-	return c[i]
-}
-
-// sliceOrFloatMap is a type constraint for a slice or a map.
-type sliceOrFloatMap interface {
-	type []int, map[float64]int
-}
-
-// This function is INVALID.
-// In this example the input type of the index operation is either
-// int (for a slice) or float64 (for a map), so the operation is
-// not permitted.
-func FloatEntry[T sliceOrFloatMap](c T) int {
-	return c[1.0] // INVALID: input type is either int or float64.
-}
-```
-
-Imposing this restriction makes it easier to reason about the type of
-some operation in a generic function.
-It avoids introducing the notion of a value whose type is the union of
-a set of types found by applying some operation to each element of a
-type list.
-
-(Note: with more understanding of how people want to write code, it
-may be possible to relax this restriction in the future.)
-
-#### Type parameters in type lists
-
-A type literal in a constraint can refer to type parameters of the
-constraint.
-In this example, the generic function `Map` takes two type parameters.
-The first type parameter is required to have an underlying type that
-is a slice of the second type parameter.
-There are no constraints on the second slice parameter.
-
-```
-// SliceConstraint is a type constraint that matches a slice of
-// the type parameter.
-type SliceConstraint[T any] interface {
-	type []T
-}
-
-// Map takes a slice of some element type and a transformation function,
-// and returns a slice of the function applied to each element.
-// Map returns a slice that is the same type as its slice argument,
-// even if that is a defined type.
-func Map[S SliceConstraint[E], E any](s S, f func(E) E) S {
-	r := make(S, len(s))
-	for i, v := range s {
-		r[i] = f(v)
-	}
-	return r
-}
-
-// MySlice is a simple defined type.
-type MySlice []int
-
-// DoubleMySlice takes a value of type MySlice and returns a new
-// MySlice value with each element doubled in value.
-func DoubleMySlice(s MySlice) MySlice {
-	// The type arguments listed explicitly here could be inferred.
-	v := Map[MySlice, int](s, func(e int) int { return 2 * e })
-	// Here v has type MySlice, not type []int.
-	return v
-}
-```
-
-We showed other examples of this earlier in the discussion of
-[constraint type inference](#Constraint-type-inference).
-
-#### Type conversions
-
-In a function with two type parameters `From` and `To`, a value of
-type `From` may be converted to a value of type `To` if all the
-types accepted by `From`'s constraint can be converted to all the
-types accepted by `To`'s constraint.
-If either type parameter does not have a type list, type conversions
-are not permitted.
-
-This is a consequence of the general rule that a generic function may
-use any operation that is permitted by all types listed in the type
-list.
-
-For example:
-
-```
-type integer interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr
-}
-
-func Convert[To, From integer](from From) To {
-	to := To(from)
-	if From(to) != from {
-		panic("conversion out of range")
-	}
-	return to
-}
-```
-
-The type conversions in `Convert` are permitted because Go permits
-every integer type to be converted to every other integer type.
-
-#### Untyped constants
-
-Some functions use untyped constants.
-An untyped constant is permitted with a value of a type parameter if
-it is permitted with every type accepted by the type parameter's
-constraint.
-
-As with type conversions, this is a consequence of the general rule
-that a generic function may use any operation that is permitted by all
-types listed in the type list.
-
-```
-type integer interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr
-}
-
-func Add10[T integer](s []T) {
-	for i, v := range s {
-		s[i] = v + 10 // OK: 10 can convert to any integer type
-	}
-}
-
-// This function is INVALID.
-func Add1024[T integer](s []T) {
-	for i, v := range s {
-		s[i] = v + 1024 // INVALID: 1024 not permitted by int8/uint8
-	}
-}
-```
-
-#### Type lists in embedded constraints
-
-When a constraint embeds another constraint, the type list of the
-final constraint is the intersection of all the type lists involved.
-If there are multiple embedded types, intersection preserves the
-property that any  type argument must satisfy the requirements of all
-embedded types.
-
-```
-// Addable is types that support the + operator.
-type Addable interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr,
-		float32, float64, complex64, complex128,
-		string
-}
-
-// Byteseq is a byte sequence: either string or []byte.
-type Byteseq interface {
-	type string, []byte
-}
-
-// AddableByteseq is a byte sequence that supports +.
-// This is every type is that is both Addable and Byteseq.
-// In other words, just the type string.
-type AddableByteseq interface {
-	Addable
-	Byteseq
-}
-```
-
-#### General notes on type lists
-
-It may seem awkward to explicitly list types in a constraint, but it
-is clear both as to which type arguments are permitted at the call
-site, and which operations are permitted by the generic function.
-
-If the language later changes to support operator methods (there are
-no such plans at present), then constraints will handle them as they
-do any other kind of method.
-
-There will always be a limited number of predeclared types, and a
-limited number of operators that those types support.
-Future language changes will not fundamentally change those facts, so
-this approach will continue to be useful.
-
-This approach does not attempt to handle every possible operator.
-The expectation is that composite types will normally be handled using
-composite types in generic function and type declarations, rather than
-putting composite types in a type list.
-For example, we expect functions that want to index into a slice to be
-parameterized on the slice element type `T`, and to use parameters or
-variables of type `[]T`.
-
-As shown in the `DoubleMySlice` example above, this approach makes it
-awkward to declare generic functions that accept and return a
-composite type and want to return the same result type as their
-argument type.
-Defined composite types are not common, but they do arise.
-This awkwardness is a weakness of this approach.
-Constraint type inference can help at the call site.
-
-### Reflection
-
-We do not propose to change the reflect package in any way.
-When a type or function is instantiated, all of the type parameters
-will become ordinary non-generic types.
-The `String` method of a `reflect.Type` value of an instantiated type
-will return the name with the type arguments in square brackets.
-For example, `List[int]`.
-
-It's impossible for non-generic code to refer to generic code without
-instantiating it, so there is no reflection information for
-uninstantiated generic types or functions.
-
-### Implementation
-
-Russ Cox [famously observed](https://research.swtch.com/generic) that
-generics require choosing among slow programmers, slow compilers, or
-slow execution times.
-
-We believe that this design permits different implementation choices.
-Code may be compiled separately for each set of type arguments, or it
-may be compiled as though each type argument is handled similarly to
-an interface type with method calls, or there may be some combination
-of the two.
-
-In other words, this design permits people to stop choosing slow
-programmers, and permits the implementation to decide between slow
-compilers (compile each set of type arguments separately) or slow
-execution times (use method calls for each operation on a value of a
-type argument).
-
-### Summary
-
-While this document is long and detailed, the actual design reduces to
-a few major points.
-
-* Functions and types can have type parameters, which are defined
-  using constraints, which are interface types.
-* Constraints describe the methods required and the types permitted
-  for a type argument.
-* Constraints describe the methods and operations permitted for a type
-  parameter.
-* Type inference will often permit omitting type arguments when
-  calling functions with type parameters.
-
-This design is completely backward compatible.
-
-We believe that this design addresses people's needs for generic
-programming in Go, without making the language any more complex than
-necessary.
-
-We can't truly know the impact on the language without years of
-experience with this design.
-That said, here are some speculations.
-
-#### Complexity
-
-One of the great aspects of Go is its simplicity.
-Clearly this design makes the language more complex.
-
-We believe that the increased complexity is small for people reading
-well written generic code, rather than writing it.
-Naturally people must learn the new syntax for declaring type
-parameters.
-This new syntax, and the new support for type lists in interfaces, are
-the only new syntactic constructs in this design.
-The code within a generic function reads like ordinary Go code, as can
-be seen in the examples below.
-It is an easy shift to go from `[]int` to `[]T`.
-Type parameter constraints serve effectively as documentation,
-describing the type.
-
-We expect that most packages will not define generic types or
-functions, but many packages are likely to use generic types or
-functions defined elsewhere.
-In the common case, generic functions work exactly like non-generic
-functions: you simply call them.
-Type inference means that you do not have to write out the type
-arguments explicitly.
-The type inference rules are designed to be unsurprising: either the
-type arguments are deduced correctly, or the call fails and requires
-explicit type parameters.
-Type inference uses type equivalence, with no attempt to resolve two
-types that are similar but not equivalent, which removes significant
-complexity.
-
-Packages using generic types will have to pass explicit type
-arguments.
-The syntax for this is straightforward.
-The only change is passing arguments to types rather than only to
-functions.
-
-In general, we have tried to avoid surprises in the design.
-Only time will tell whether we succeeded.
-
-#### Pervasiveness
-
-We expect that a few new packages will be added to the standard
-library.
-A new `slices` packages will be similar to the existing bytes and
-strings packages, operating on slices of any element type.
-New `maps` and `chans` packages will provide algorithms that are
-currently duplicated for each element type.
-A `sets` package may be added.
-
-A new `constraints` package will provide standard constraints, such as
-constraints that permit all integer types or all numeric types.
-
-Packages like `container/list` and `container/ring`, and types like
-`sync.Map` and `sync/atomic.Value`, will be updated to be compile-time
-type-safe, either using new names or new versions of the packages.
-
-The `math` package will be extended to provide a set of simple
-standard algorithms for all numeric types, such as the ever popular
-`Min` and `Max` functions.
-
-We may add generic variants to the `sort` package.
-
-It is likely that new special purpose compile-time type-safe container
-types will be developed.
-
-We do not expect approaches like the C++ STL iterator types to become
-widely used.
-In Go that sort of idea is more naturally expressed using an interface
-type.
-In C++ terms, using an interface type for an iterator can be seen as
-carrying an abstraction penalty, in that run-time efficiency will be
-less than C++ approaches that in effect inline all code; we believe
-that Go programmers will continue to find that sort of penalty to be
-acceptable.
-
-As we get more container types, we may develop a standard `Iterator`
-interface.
-That may in turn lead to pressure to modify the language to add some
-mechanism for using an `Iterator` with the `range` clause.
-That is very speculative, though.
-
-#### Efficiency
-
-It is not clear what sort of efficiency people expect from generic
-code.
-
-Generic functions, rather than generic types, can probably be compiled
-using an interface-based approach.
-That will optimize compile time, in that the function is only compiled
-once, but there will be some run time cost.
-
-Generic types may most naturally be compiled multiple times for each
-set of type arguments.
-This will clearly carry a compile time cost, but there shouldn't be
-any run time cost.
-Compilers can also choose to implement generic types similarly to
-interface types, using special purpose methods to access each element
-that depends on a type parameter.
-
-Only experience will show what people expect in this area.
-
-#### Omissions
-
-We believe that this design covers the basic requirements for
-generic programming.
-However, there are a number of programming constructs that are not
-supported.
-
-* No specialization.
-  There is no way to write multiple versions of a generic function
-  that are designed to work with specific type arguments.
-* No metaprogramming.
-  There is no way to write code that is executed at compile time to
-  generate code to be executed at run time.
-* No higher level abstraction.
-  There is no way to use a function with type arguments other than to
-  call it or instantiate it.
-  There is no way to use a generic type other than to instantiate it.
-* No general type description.
-  In order to use operators in a generic function, constraints list
-  specific types, rather than describing the characteristics that a
-  type must have.
-  This is easy to understand but may be limiting at times.
-* No covariance or contravariance of function parameters.
-* No operator methods.
-  You can write a generic container that is compile-time type-safe,
-  but you can only access it with ordinary methods, not with syntax
-  like `c[k]`.
-* No currying.
-  There is no way to partially instantiate a generic function or type,
-  other than by using a helper function or a wrapper type.
-  All type arguments must be either explicitly passed or inferred at
-  instantiation time.
-* No variadic type parameters.
-  There is no support for variadic type parameters, which would permit
-  writing a single generic function that takes different numbers of
-  both type parameters and regular parameters.
-* No adaptors.
-  There is no way for a constraint to define adaptors that could be
-  used to support type arguments that do not already implement the
-  constraint, such as, for example, defining an `==` operator in terms
-  of an `Equal` method, or vice-versa.
-* No parameterization on non-type values such as constants.
-  This arises most obviously for arrays, where it might sometimes be
-  convenient to write `type Matrix[n int] [n][n]float64`.
-  It might also sometimes be useful to specify significant values for
-  a container type, such as a default value for elements.
-
-#### Issues
-
-There are some issues with this design that deserve a more detailed
-discussion.
-We think these issues are relatively minor compared to the design as a
-whole, but they still deserve a complete hearing and discussion.
-
-##### The zero value
-
-This design has no simple expression for the zero value of a type
-parameter.
-For example, consider this implementation of optional values that uses
-pointers:
-
-```
-type Optional[T any] struct {
-	p *T
-}
-
-func (o Optional[T]) Val() T {
-	if o.p != nil {
-		return *o.p
-	}
-	var zero T
-	return zero
-}
-```
-
-In the case where `o.p == nil`, we want to return the zero value of
-`T`, but we have no way to write that.
-It would be nice to be able to write `return nil`, but that wouldn't
-work if `T` is, say, `int`; in that case we would have to write
-`return 0`.
-And, of course, there is no way to write a constraint to support
-either `return nil` or `return 0`.
-
-Some approaches to this are:
-
-* Use `var zero T`, as above, which works with the existing design
-  but requires an extra statement.
-* Use `*new(T)`, which is cryptic but works with the existing
-  design.
-* For results only, name the result parameter, and use a naked
-  `return` statement to return the zero value.
-* Extend the design to permit using `nil` as the zero value of any
-  generic type (but see [issue 22729](https://golang.org/issue/22729)).
-* Extend the design to permit using `T{}`, where `T` is a type
-  parameter, to indicate the zero value of the type.
-* Change the language to permit using `_` on the right hand of an
-  assignment (including `return` or a function call) as proposed in
-  [issue 19642](https://golang.org/issue/19642).
-* Change the language to permit `return ...` to return zero values of
-  the result types, as proposed in
-  [issue 21182](https://golang.org/issue/21182).
-
-We feel that more experience with this design is needed before
-deciding what, if anything, to do here.
-
-##### Identifying the matched predeclared type
-
-The design doesn't provide any way to test the underlying type matched
-by a type argument.
-Code can test the actual type argument through the somewhat awkward
-approach of converting to an empty interface type and using a type
-assertion or a type switch.
-But that lets code test the actual type argument, which is not the
-same as the underlying type.
-
-Here is an example that shows the difference.
-
-```
-type Float interface {
-	type float32, float64
-}
-
-func NewtonSqrt[T Float](v T) T {
-	var iterations int
-	switch (interface{})(v).(type) {
-	case float32:
-		iterations = 4
-	case float64:
-		iterations = 5
-	default:
-		panic(fmt.Sprintf("unexpected type %T", v))
-	}
-	// Code omitted.
-}
-
-type MyFloat float32
-
-var G = NewtonSqrt(MyFloat(64))
-```
-
-This code will panic when initializing `G`, because the type of `v` in
-the `NewtonSqrt` function will be `MyFloat`, not `float32` or
-`float64`.
-What this function actually wants to test is not the type of `v`, but
-the type that `v` matched in the constraint.
-
-One way to handle this would be to permit type switches on the type
-`T`, with the proviso that the type `T` would always match a type
-defined in the constraint.
-This kind of type switch would only be permitted if the constraint
-lists explicit types, and only types listed in the constraint would be
-permitted as cases.
-
-##### No way to express convertibility
-
-The design has no way to express convertibility between two different
-type parameters.
-For example, there is no way to write this function:
-
-```
-// Copy copies values from src to dst, converting them as they go.
-// It returns the number of items copied, which is the minimum of
-// the lengths of dst and src.
-// This implementation is INVALID.
-func Copy[T1, T2 any](dst []T1, src []T2) int {
-	for i, x := range src {
-		if i > len(dst) {
-			return i
-		}
-		dst[i] = T1(x) // INVALID
-	}
-	return len(src)
-}
-```
-
-The conversion from type `T2` to type `T1` is invalid, as there is no
-constraint on either type that permits the conversion.
-Worse, there is no way to write such a constraint in general.
-In the particular case where both `T1` and `T2` can require some type
-list, then this function can be written as described earlier when
-discussing [type conversions using type lists](#Type-conversions).
-But, for example, there is no way to write a constraint for the case
-in which `T1` is an interface type and `T2` is a type that implements
-that interface.
-
-It's worth noting that if `T1` is an interface type then this can be
-written using a conversion to the empty interface type and a type
-assertion, but this is, of course, not compile-time type-safe.
-
-```
-// Copy copies values from src to dst, converting them as they go.
-// It returns the number of items copied, which is the minimum of
-// the lengths of dst and src.
-func Copy[T1, T2 any](dst []T1, src []T2) int {
-	for i, x := range src {
-		if i > len(dst) {
-			return i
-		}
-		dst[i] = (interface{})(x).(T1)
-	}
-	return len(src)
-}
-```
-
-##### No parameterized methods
-
-This design draft does not permit methods to declare type parameters
-that are specific to the method.
-The receiver may have type parameters, but the method may not add any
-type parameters.
-
-In Go, one of the main roles of methods is to permit types to
-implement interfaces.
-It is not clear whether it is reasonably possible to permit
-parameterized methods to implement interfaces.
-For example, consider this code, which uses the obvious syntax for
-parameterized methods.
-This code uses multiple packages to make the problem clearer.
-
-```
-package p1
-
-// S is a type with a parameterized method Identity.
-type S struct{}
-
-// Identity is a simple identity method that works for any type.
-func (S) Identity[T any](v T) T { return v }
-
-package p2
-
-// HasIdentity is an interface that matches any type with a
-// parameterized Identity method.
-type HasIdentity interface {
-	Identity[T any](T) T
-}
-
-package p3
-
-import "p2"
-
-// CheckIdentity checks the Identity method if it exists.
-// Note that although this function calls a parameterized method,
-// this function is not itself parameterized.
-func CheckIdentity(v interface{}) {
-	if vi, ok := v.(p2.HasIdentity); ok {
-		if got := vi.Identity[int](0); got != 0 {
-			panic(got)
-		}
-	}
-}
-
-package p4
-
-import (
-	"p1"
-	"p3"
-)
-
-// CheckSIdentity passes an S value to CheckIdentity.
-func CheckSIdentity() {
-	p3.CheckIdentity(p1.S{})
-}
-```
-
-In this example, we have a type `p1.S` with a parameterized method and
-a type `p2.HasIdentity` that also has a parameterized method.
-`p1.S` implements `p2.HasIdentity`.
-Therefore, the function `p3.CheckIdentity` can call `vi.Identity` with
-an `int` argument, which in the call from `p4.CheckSIdentity` will be
-a call to `p1.S.Identity[int]`.
-But package p3 does not know anything about the type `p1.S`.
-There may be no other call to `p1.S.Identity` elsewhere in the
-program.
-We need to instantiate `p1.S.Identity[int]` somewhere, but how?
-
-We could instantiate it at link time, but in the general case that
-requires the linker to traverse the complete call graph of the program
-to determine the set of types that might be passed to `CheckIdentity`.
-And even that traversal is not sufficient in the general case when
-type reflection gets involved, as reflection might look up methods
-based on strings input by the user.
-So in general instantiating parameterized methods in the linker might
-require instantiating every parameterized method for every possible
-type argument, which seems untenable.
-
-Or, we could instantiate it at run time.
-In general this means using some sort of JIT, or compiling the code to
-use some sort of reflection based approach.
-Either approach would be very complex to implement, and would be
-surprisingly slow at run time.
-
-Or, we could decide that parameterized methods do not, in fact,
-implement interfaces, but then it's much less clear why we need
-methods at all.
-If we disregard interfaces, any parameterized method can be
-implemented as a parameterized function.
-
-So while parameterized methods seem clearly useful at first glance, we
-would have to decide what they mean and how to implement that.
-
-##### No way to require pointer methods
-
-In some cases a parameterized function is naturally written such that
-it always invokes methods on addressable values.
-For example, this happens when calling a method on each element of a
-slice.
-In such a case, the function only requires that the method be in the
-slice element type's pointer method set.
-The type constraints described in this design draft have no way to
-write that requirement.
-
-For example, consider a variant of the `Stringify` example we [showed
-earlier](#Using-a-constraint).
-
-```
-// Stringify2 calls the String method on each element of s,
-// and returns the results.
-func Stringify2[T Stringer](s []T) (ret []string) {
-	for i := range s {
-		ret = append(ret, s[i].String())
-	}
-	return ret
-}
-```
-
-Suppose we have a `[]bytes.Buffer` and we want to convert it into a
-`[]string`.
-The `Stringify2` function here won't help us.
-We want to write `Stringify2[bytes.Buffer]`, but we can't, because
-`bytes.Buffer` doesn't have a `String` method.
-The type that has a `String` method is `*bytes.Buffer`.
-Writing `Stringify2[*bytes.Buffer]` doesn't help because that function
-expects a `[]*bytes.Buffer`, but we have a `[]bytes.Buffer`.
-
-We discussed a similar case in the [pointer method
-example](#Pointer-method-example) above.
-There we used constraint type inference to help simplify the problem.
-Here that doesn't help, because `Stringify2` doesn't really care about
-calling a pointer method.
-It just wants a type that has a `String` method, and it's OK if the
-method is only in the pointer method set, not the value method set.
-But we also want to accept the case where the method is in the value
-method set, for example if we really do have a `[]*bytes.Buffer`.
-
-What we need is a way to say that the type constraint applies to
-either the pointer method set or the value method set.
-The body of the function would be required to only call the method on
-addressable values of the type.
-
-It's not clear how often this problem comes up in practice.
-
-##### No association between float and complex
-
-Constraint type inference lets us give a name to the element of a
-slice type, and to apply other similar type decompositions.
-However, there is no way to associate a float type and a complex type.
-For example, there is no way to write the predeclared `real`, `imag`,
-or `complex` functions with this design draft.
-There is no way to say "if the argument type is `complex64`, then the
-result type is `float32`."
-
-One possible approach here would be to permit `real(T)` as a type
-constraint meaning "the float type associated with the complex type
-`T`".
-Similarly, `complex(T)` would mean "the complex type associated with
-the floating point type `T`".
-Constraint type inference would simplify the call site.
-However, that would be unlike other type constraints.
-
-#### Discarded ideas
-
-This design is not perfect, and there may be ways to improve it.
-That said, there are many ideas that we've already considered in
-detail.
-This section lists some of those ideas in the hopes that it will help
-to reduce repetitive discussion.
-The ideas are presented in the form of a FAQ.
-
-##### What happened to contracts?
-
-An earlier draft design of generics implemented constraints using a
-new language construct called contracts.
-Type lists appeared only in contracts, rather than on interface
-types.
-However, many people had a hard time understanding the difference
-between contracts and interface types.
-It also turned out that contracts could be represented as a set of
-corresponding interfaces; there was no loss in expressive power
-without contracts.
-We decided to simplify the approach to use only interface types.
-
-##### Why not use methods instead of type lists?
-
-_Type lists are weird._
-_Why not write methods for all operators?_
-
-It is possible to permit operator tokens as method names, leading to
-methods such as `+(T) T`.
-Unfortunately, that is not sufficient.
-We would need some mechanism to describe a type that matches any
-integer type, for operations such as shifts `<<(integer) T` and
-indexing `[](integer) T` which are not restricted to a single int
-type.
-We would need an untyped boolean type for operations such as `==(T)
-untyped bool`.
-We would need to introduce new notation for operations such as
-conversions, or to express that one may range over a type, which would
-likely require some new syntax.
-We would need some mechanism to describe valid values of untyped
-constants.
-We would have to consider whether support for `<(T) bool` means that a
-generic function can also use `<=`, and similarly whether support for
-`+(T) T` means that a function can also use `++`.
-It might be possible to make this approach work but it's not
-straightforward.
-The approach used in this design seems simpler and relies on only one
-new syntactic construct (type lists) and one new name (`comparable`).
-
-##### Why not put type parameters on packages?
-
-We investigated this extensively.
-It becomes problematic when you want to write a `list` package, and
-you want that package to include a `Transform` function that converts
-a `List` of one element type to a `List` of another element type.
-It's very awkward for a function in one instantiation of a package to
-return a type that requires a different instantiation of the same
-package.
-
-It also confuses package boundaries with type definitions.
-There is no particular reason to think that the uses of generic types
-will break down neatly into packages.
-Sometimes they will, sometimes they won't.
-
-##### Why not use the syntax `F<T>` like C++ and Java?
-
-When parsing code within a function, such as `v := F<T>`, at the point
-of seeing the `<` it's ambiguous whether we are seeing a type
-instantiation or an expression using the `<` operator.
-This is very difficult to resolve without type information.
-
-For example, consider a statement like
-
-```
-	a, b = w < x, y > (z)
-```
-
-Without type information, it is impossible to decide whether the right
-hand side of the assignment is a pair of expressions (`w < x` and `y >
-(z)`), or whether it is a generic function instantiation and call that
-returns two result values (`(w<x, y>)(z)`).
-
-It is a key design decision of Go that parsing be possible without
-type information, which seems impossible when using angle brackets for
-generics.
-
-##### Why not use the syntax `F(T)`?
-
-An earlier version of this design draft used that syntax.
-It was workable but it introduced several parsing ambiguities.
-For example, when writing `var f func(x(T))` it wasn't clear whether
-this the type was a function with a single unnamed parameter of the
-instantiated type `x(T)` or whether it was a function with a parameter
-named `x` with type `(T)` (more usually written as `func(x T)`, but in
-this case with a parenthesized type).
-
-There were other ambiguities as well.
-For `[]T(v1)` and `[]T(v2){}`, at the point of the open parentheses we
-don't know whether this is a type conversion (of the value `v1` to the
-type `[]T`) or a type literal (whose type is the instantiated type
-`T(v2)`).
-For `interface { M(T) }` we don't know whether this an interface with
-a method `M` or an interface with an embedded instantiated interface
-`M(T)`.
-These ambiguities are solvable, by adding more parentheses, but
-awkward.
-
-Also some people were troubled by the number of parenthesized lists
-involved in declarations like `func F(T any)(v T)(r1, r2 T)` or in
-calls like `F(int)(1)`.
-
-##### Why not use `F«T»`?
-
-We considered it but we couldn't bring ourselves to require
-non-ASCII.
-
-##### Why not define constraints in a builtin package?
-
-_Instead of writing out type lists, use names like_
-_`constraints.Arithmetic` and `constraints.Comparable`._
-
-Listing all the possible combinations of types gets rather lengthy.
-It also introduces a new set of names that not only the writer of
-generic code, but, more importantly, the reader, must remember.
-One of the driving goals of this design is to introduce as few new
-names as possible.
-In this design we introduce only two new predeclared names,
-`comparable` and `any`.
-
-We expect that if people find such names useful, we can introduce a
-package `constraints` that defines those names in the form of
-constraints that can be used by other types and functions and embedded
-in other constraints.
-That will define the most useful names in the standard library while
-giving programmers the flexibility to use other combinations of types
-where appropriate.
-
-##### Why not permit type assertions on values whose type is a type parameter?
-
-In an earlier version of this design, we permitted using type
-assertions and type switches on variables whose type was a type
-parameter, or whose type was based on a type parameter.
-We removed this facility because it is always possible to convert a
-value of any type to the empty interface type, and then use a type
-assertion or type switch on that.
-Also, it was sometimes confusing that in a constraint with a type
-list, a type assertion or type switch would use the actual type
-argument, not the underlying type of the type argument (the difference
-is explained in the section on [identifying the matched predeclared
-type](#Identifying-the-matched-predeclared-type)).
-
-#### Comparison with Java
-
-Most complaints about Java generics center around type erasure.
-This design does not have type erasure.
-The reflection information for a generic type will include the full
-compile-time type information.
-
-In Java type wildcards (`List<? extends Number>`, `List<? super
-Number>`) implement covariance and contravariance.
-These concepts are missing from Go, which makes generic types much
-simpler.
-
-#### Comparison with C++
-
-C++ templates do not enforce any constraints on the type arguments
-(unless the concept proposal is adopted).
-This means that changing template code can accidentally break far-off
-instantiations.
-It also means that error messages are reported only at instantiation
-time, and can be deeply nested and difficult to understand.
-This design avoids these problems through mandatory and explicit
-constraints.
-
-C++ supports template metaprogramming, which can be thought of as
-ordinary programming done at compile time using a syntax that is
-completely different than that of non-template C++.
-This design has no similar feature.
-This saves considerable complexity while losing some power and run
-time efficiency.
-
-C++ uses two-phase name lookup, in which some names are looked up in
-the context of the template definition, and some names are looked up
-in the context of the template instantiation.
-In this design all names are looked up at the point where they are
-written.
-
-In practice, all C++ compilers compile each template at the point
-where it is instantiated.
-This can slow down compilation time.
-This design offers flexibility as to how to handle the compilation of
-generic functions.
-
-#### Comparison with Rust
-
-The generics described in this design are similar to generics in
-Rust.
-
-One difference is that in Rust the association between a trait bound
-and a type must be defined explicitly, either in the crate that
-defines the trait bound or the crate that defines the type.
-In Go terms, this would mean that we would have to declare somewhere
-whether a type satisfied a constraint.
-Just as Go types can satisfy Go interfaces without an explicit
-declaration, in this design Go type arguments can satisfy a constraint
-without an explicit declaration.
-
-Where this design uses type lists, the Rust standard library defines
-standard traits for operations like comparison.
-These standard traits are automatically implemented by Rust's
-primitive types, and can be implemented by user defined types as
-well.
-Rust provides a fairly extensive list of traits, at least 34, covering
-all of the operators.
-
-Rust supports type parameters on methods, which this design does not.
-
-## Examples
-
-The following sections are examples of how this design could be used.
-This is intended to address specific areas where people have created
-user experience reports concerned with Go's lack of generics.
-
-### Map/Reduce/Filter
-
-Here is an example of how to write map, reduce, and filter functions
-for slices.
-These functions are intended to correspond to the similar functions in
-Lisp, Python, Java, and so forth.
-
-```
-// Package slices implements various slice algorithms.
-package slices
-
-// Map turns a []T1 to a []T2 using a mapping function.
-// This function has two type parameters, T1 and T2.
-// This works with slices of any type.
-func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 {
-	r := make([]T2, len(s))
-	for i, v := range s {
-		r[i] = f(v)
-	}
-	return r
-}
-
-// Reduce reduces a []T1 to a single value using a reduction function.
-func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 {
-	r := initializer
-	for _, v := range s {
-		r = f(r, v)
-	}
-	return r
-}
-
-// Filter filters values from a slice using a filter function.
-// It returns a new slice with only the elements of s
-// for which f returned true.
-func Filter[T any](s []T, f func(T) bool) []T {
-	var r []T
-	for _, v := range s {
-		if f(v) {
-			r = append(r, v)
-		}
-	}
-	return r
-}
-```
-
-Here are some example calls of these functions.
-Type inference is used to determine the type arguments based on the
-types of the non-type arguments.
-
-```
-	s := []int{1, 2, 3}
-
-	floats := slices.Map(s, func(i int) float64 { return float64(i) })
-	// Now floats is []float64{1.0, 2.0, 3.0}.
-
-	sum := slices.Reduce(s, 0, func(i, j int) int { return i + j })
-	// Now sum is 6.
-
-	evens := slices.Filter(s, func(i int) bool { return i%2 == 0 })
-	// Now evens is []int{2}.
-```
-
-### Map keys
-
-Here is how to get a slice of the keys of any map.
-
-```
-// Package maps provides general functions that work for all map types.
-package maps
-
-// Keys returns the keys of the map m in a slice.
-// The keys will be returned in an unpredictable order.
-// This function has two type parameters, K and V.
-// Map keys must be comparable, so key has the predeclared
-// constraint comparable. Map values can be any type.
-func Keys[K comparable, V any](m map[K]V) []K {
-	r := make([]K, 0, len(m))
-	for k := range m {
-		r = append(r, k)
-	}
-	return r
-}
-```
-
-In typical use the map key and val types will be inferred.
-
-```
-	k := maps.Keys(map[int]int{1:2, 2:4})
-	// Now k is either []int{1, 2} or []int{2, 1}.
-```
-
-### Sets
-
-Many people have asked for Go's builtin map type to be extended, or
-rather reduced, to support a set type.
-Here is a type-safe implementation of a set type, albeit one that uses
-methods rather than operators like `[]`.
-
-```
-// Package sets implements sets of any comparable type.
-package sets
-
-// Set is a set of values.
-type Set[T comparable] map[T]struct{}
-
-// Make returns a set of some element type.
-func Make[T comparable]() Set[T] {
-	return make(Set[T])
-}
-
-// Add adds v to the set s.
-// If v is already in s this has no effect.
-func (s Set[T]) Add(v T) {
-	s[v] = struct{}{}
-}
-
-// Delete removes v from the set s.
-// If v is not in s this has no effect.
-func (s Set[T]) Delete(v T) {
-	delete(s, v)
-}
-
-// Contains reports whether v is in s.
-func (s Set[T]) Contains(v T) bool {
-	_, ok := s[v]
-	return ok
-}
-
-// Len reports the number of elements in s.
-func (s Set[T]) Len() int {
-	return len(s)
-}
-
-// Iterate invokes f on each element of s.
-// It's OK for f to call the Delete method.
-func (s Set[T]) Iterate(f func(T)) {
-	for v := range s {
-		f(v)
-	}
-}
-```
-
-Example use:
-
-```
-	// Create a set of ints.
-	// We pass int as a type argument.
-	// Then we write () because Make does not take any non-type arguments.
-	// We have to pass an explicit type argument to Make.
-	// Function argument type inference doesn't work because the
-	// type argument to Make is only used for a result parameter type.
-	s := sets.Make[int]()
-
-	// Add the value 1 to the set s.
-	s.Add(1)
-
-	// Check that s does not contain the value 2.
-	if s.Contains(2) { panic("unexpected 2") }
-```
-
-This example shows how to use this design to provide a compile-time
-type-safe wrapper around an existing API.
-
-### Sort
-
-Before the introduction of `sort.Slice`, a common complaint was the
-need for boilerplate definitions in order to use `sort.Sort`.
-With this design, we can add to the sort package as follows:
-
-```
-// Ordered is a type constraint that matches all ordered types.
-// (An ordered type is one that supports the < <= >= > operators.)
-// In practice this type constraint would likely be defined in
-// a standard library package.
-type Ordered interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr,
-		float32, float64,
-		string
-}
-
-// orderedSlice is an internal type that implements sort.Interface.
-// The Less method uses the < operator. The Ordered type constraint
-// ensures that T has a < operator.
-type orderedSlice[T Ordered] []T
-
-func (s orderedSlice[T]) Len() int           { return len(s) }
-func (s orderedSlice[T]) Less(i, j int) bool { return s[i] < s[j] }
-func (s orderedSlice[T]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-
-// OrderedSlice sorts the slice s in ascending order.
-// The elements of s must be ordered using the < operator.
-func OrderedSlice[T Ordered](s []T) {
-	// Convert s to the type orderedSlice[T].
-	// As s is []T, and orderedSlice[T] is defined as []T,
-	// this conversion is permitted.
-	// orderedSlice[T] implements sort.Interface,
-	// so can pass the result to sort.Sort.
-	// The elements will be sorted using the < operator.
-	sort.Sort(orderedSlice[T](s))
-}
-```
-
-Now we can write:
-
-```
-	s1 := []int32{3, 5, 2}
-	sort.OrderedSlice(s1)
-	// Now s1 is []int32{2, 3, 5}
-
-	s2 := []string{"a", "c", "b"})
-	sort.OrderedSlice(s2)
-	// Now s2 is []string{"a", "b", "c"}
-```
-
-Along the same lines, we can add a function for sorting using a
-comparison function, similar to `sort.Slice` but writing the function
-to take values rather than slice indexes.
-
-```
-// sliceFn is an internal type that implements sort.Interface.
-// The Less method calls the cmp field.
-type sliceFn[T any] struct {
-	s   []T
-	cmp func(T, T) bool
-}
-
-func (s sliceFn[T]) Len() int           { return len(s.s) }
-func (s sliceFn[T]) Less(i, j int) bool { return s.cmp(s.s[i], s.s[j]) }
-func (s sliceFn[T]) Swap(i, j int)      { s.s[i], s.s[j] = s.s[j], s.s[i] }
-
-// SliceFn sorts the slice s according to the function cmp.
-func SliceFn[T any](s []T, cmp func(T, T) bool) {
-	sort.Sort(sliceFn[E]{s, cmp})
-}
-```
-
-An example of calling this might be:
-
-```
-	var s []*Person
-	// ...
-	sort.SliceFn(s, func(p1, p2 *Person) bool { return p1.Name < p2.Name })
-```
-
-### Channels
-
-Many simple general purpose channel functions are never written,
-because they must be written using reflection and the caller must type
-assert the results.
-With this design they become straightforward to write.
-
-```
-// Package chans implements various channel algorithms.
-package chans
-
-import "runtime"
-
-// Drain drains any elements remaining on the channel.
-func Drain[T any](c <-chan T) {
-	for range c {
-	}
-}
-
-// Merge merges two channels of some element type into a single channel.
-func Merge[T any](c1, c2 <-chan T) <-chan T {
-	r := make(chan T)
-	go func(c1, c2 <-chan T, r chan<- T) {
-		defer close(r)
-		for c1 != nil || c2 != nil {
-			select {
-			case v1, ok := <-c1:
-				if ok {
-					r <- v1
-				} else {
-					c1 = nil
-				}
-			case v2, ok := <-c2:
-				if ok {
-					r <- v2
-				} else {
-					c2 = nil
-				}
-			}
-		}
-	}(c1, c2, r)
-	return r
-}
-
-// Ranger provides a convenient way to exit a goroutine sending values
-// when the receiver stops reading them.
-//
-// Ranger returns a Sender and a Receiver. The Receiver provides a
-// Next method to retrieve values. The Sender provides a Send method
-// to send values and a Close method to stop sending values. The Next
-// method indicates when the Sender has been closed, and the Send
-// method indicates when the Receiver has been freed.
-func Ranger[T any]() (*Sender[T], *Receiver[T]) {
-	c := make(chan T)
-	d := make(chan bool)
-	s := &Sender[T]{values: c, done: d}
-	r := &Receiver[T]{values: c, done: d}
-	// The finalizer on the receiver will tell the sender
-	// if the receiver stops listening.
-	runtime.SetFinalizer(r, r.finalize)
-	return s, r
-}
-
-// A Sender is used to send values to a Receiver.
-type Sender[T any] struct {
-	values chan<- T
-	done   <-chan bool
-}
-
-// Send sends a value to the receiver. It reports whether any more
-// values may be sent; if it returns false the value was not sent.
-func (s *Sender[T]) Send(v T) bool {
-	select {
-	case s.values <- v:
-		return true
-	case <-s.done:
-		// The receiver has stopped listening.
-		return false
-	}
-}
-
-// Close tells the receiver that no more values will arrive.
-// After Close is called, the Sender may no longer be used.
-func (s *Sender[T]) Close() {
-	close(s.values)
-}
-
-// A Receiver receives values from a Sender.
-type Receiver[T any] struct {
-	values <-chan T
-	done  chan<- bool
-}
-
-// Next returns the next value from the channel. The bool result
-// reports whether the value is valid. If the value is not valid, the
-// Sender has been closed and no more values will be received.
-func (r *Receiver[T]) Next() (T, bool) {
-	v, ok := <-r.values
-	return v, ok
-}
-
-// finalize is a finalizer for the receiver.
-// It tells the sender that the receiver has stopped listening.
-func (r *Receiver[T]) finalize() {
-	close(r.done)
-}
-```
-
-There is an example of using this function in the next section.
-
-### Containers
-
-One of the frequent requests for generics in Go is the ability to
-write compile-time type-safe containers.
-This design makes it easy to write a compile-time type-safe wrapper
-around an existing container; we won't write out an example for that.
-This design also makes it easy to write a compile-time type-safe
-container that does not use boxing.
-
-Here is an example of an ordered map implemented as a binary tree.
-The details of how it works are not too important.
-The important points are:
-
-* The code is written in a natural Go style, using the key and value
-  types where needed.
-* The keys and values are stored directly in the nodes of the tree,
-  not using pointers and not boxed as interface values.
-
-```
-// Package orderedmaps provides an ordered map, implemented as a binary tree.
-package orderedmaps
-
-import "chans"
-
-// Map is an ordered map.
-type Map[K, V any] struct {
-	root    *node[K, V]
-	compare func(K, K) int
-}
-
-// node is the type of a node in the binary tree.
-type node[K, V any] struct {
-	k           K
-	v           V
-	left, right *node[K, V]
-}
-
-// New returns a new map.
-// Since the type parameter V is only used for the result,
-// type inference does not work, and calls to New must always
-// pass explicit type arguments.
-func New[K, V any](compare func(K, K) int) *Map[K, V] {
-	return &Map[K, V]{compare: compare}
-}
-
-// find looks up k in the map, and returns either a pointer
-// to the node holding k, or a pointer to the location where
-// such a node would go.
-func (m *Map[K, V]) find(k K) **node[K, V] {
-	pn := &m.root
-	for *pn != nil {
-		switch cmp := m.compare(k, (*pn).k); {
-		case cmp < 0:
-			pn = &(*pn).left
-		case cmp > 0:
-			pn = &(*pn).right
-		default:
-			return pn
-		}
-	}
-	return pn
-}
-
-// Insert inserts a new key/value into the map.
-// If the key is already present, the value is replaced.
-// Reports whether this is a new key.
-func (m *Map[K, V]) Insert(k K, v V) bool {
-	pn := m.find(k)
-	if *pn != nil {
-		(*pn).v = v
-		return false
-	}
-	*pn = &node[K, V]{k: k, v: v}
-	return true
-}
-
-// Find returns the value associated with a key, or zero if not present.
-// The bool result reports whether the key was found.
-func (m *Map[K, V]) Find(k K) (V, bool) {
-	pn := m.find(k)
-	if *pn == nil {
-		var zero V // see the discussion of zero values, above
-		return zero, false
-	}
-	return (*pn).v, true
-}
-
-// keyValue is a pair of key and value used when iterating.
-type keyValue[K, V any] struct {
-	k K
-	v V
-}
-
-// InOrder returns an iterator that does an in-order traversal of the map.
-func (m *Map[K, V]) InOrder() *Iterator[K, V] {
-	type kv = keyValue[K, V] // convenient shorthand
-	sender, receiver := chans.Ranger[kv]()
-	var f func(*node[K, V]) bool
-	f = func(n *node[K, V]) bool {
-		if n == nil {
-			return true
-		}
-		// Stop sending values if sender.Send returns false,
-		// meaning that nothing is listening at the receiver end.
-		return f(n.left) &&
-			sender.Send(kv{n.k, n.v}) &&
-			f(n.right)
-	}
-	go func() {
-		f(m.root)
-		sender.Close()
-	}()
-	return &Iterator[K, V]{receiver}
-}
-
-// Iterator is used to iterate over the map.
-type Iterator[K, V any] struct {
-	r *chans.Receiver[keyValue[K, V]]
-}
-
-// Next returns the next key and value pair. The bool result reports
-// whether the values are valid. If the values are not valid, we have
-// reached the end.
-func (it *Iterator[K, V]) Next() (K, V, bool) {
-	kv, ok := it.r.Next()
-	return kv.k, kv.v, ok
-}
-```
-
-This is what it looks like to use this package:
-
-```
-import "container/orderedmaps"
-
-// Set m to an ordered map from string to string,
-// using strings.Compare as the comparison function.
-var m = orderedmaps.New[string, string](strings.Compare)
-
-// Add adds the pair a, b to m.
-func Add(a, b string) {
-	m.Insert(a, b)
-}
-```
-
-### Append
-
-The predeclared `append` function exists to replace the boilerplate
-otherwise required to grow a slice.
-Before `append` was added to the language, there was a function `Add`
-in the bytes package:
-
-```
-// Add appends the contents of t to the end of s and returns the result.
-// If s has enough capacity, it is extended in place; otherwise a
-// new array is allocated and returned.
-func Add(s, t []byte) []byte
-```
-
-`Add` appended two `[]byte` values together, returning a new slice.
-That was fine for `[]byte`, but if you had a slice of some other
-type, you had to write essentially the same code to append more
-values.
-If this design were available back then, perhaps we would not have
-added `append` to the language.
-Instead, we could write something like this:
-
-```
-// Package slices implements various slice algorithms.
-package slices
-
-// Append appends the contents of t to the end of s and returns the result.
-// If s has enough capacity, it is extended in place; otherwise a
-// new array is allocated and returned.
-func Append[T any](s []T, t ...T) []T {
-	lens := len(s)
-	tot := lens + len(t)
-	if tot < 0 {
-		panic("Append: cap out of range")
-	}
-	if tot > cap(s) {
-		news := make([]T, tot, tot + tot/2)
-		copy(news, s)
-		s = news
-	}
-	s = s[:tot]
-	copy(s[lens:], t)
-	return s
-}
-```
-
-That example uses the predeclared `copy` function, but that's OK, we
-can write that one too:
-
-```
-// Copy copies values from t to s, stopping when either slice is
-// full, returning the number of values copied.
-func Copy[T any](s, t []T) int {
-	i := 0
-	for ; i < len(s) && i < len(t); i++ {
-		s[i] = t[i]
-	}
-	return i
-}
-```
-
-These functions can be used as one would expect:
-
-```
-	s := slices.Append([]int{1, 2, 3}, 4, 5, 6)
-	// Now s is []int{1, 2, 3, 4, 5, 6}.
-	slices.Copy(s[3:], []int{7, 8, 9})
-	// Now s is []int{1, 2, 3, 7, 8, 9}
-```
-
-This code doesn't implement the special case of appending or copying a
-`string` to a `[]byte`, and it's unlikely to be as efficient as the
-implementation of the predeclared function.
-Still, this example shows that using this design would permit `append`
-and `copy` to be written generically, once, without requiring any
-additional special language features.
-
-### Metrics
-
-In a [Go experience
-report](https://medium.com/@sameer_74231/go-experience-report-for-generics-google-metrics-api-b019d597aaa4)
-Sameer Ajmani describes a metrics implementation.
-Each metric has a value and one or more fields.
-The fields have different types.
-Defining a metric requires specifying the types of the fields.
-The `Add` method takes the field types as arguments, and records an
-instance of that set of fields.
-The C++ implementation uses a variadic template.
-The Java implementation includes the number of fields in the name of
-the type.
-Both the C++ and Java implementations provide compile-time type-safe
-Add methods.
-
-Here is how to use this design to provide similar functionality in
-Go with a compile-time type-safe `Add` method.
-Because there is no support for a variadic number of type arguments,
-we must use different names for a different number of arguments, as in
-Java.
-This implementation only works for comparable types.
-A more complex implementation could accept a comparison function to
-work with arbitrary types.
-
-```
-// Package metrics provides a general mechanism for accumulating
-// metrics of different values.
-package metrics
-
-import "sync"
-
-// Metric1 accumulates metrics of a single value.
-type Metric1[T comparable] struct {
-	mu sync.Mutex
-	m  map[T]int
-}
-
-// Add adds an instance of a value.
-func (m *Metric1[T]) Add(v T) {
-	m.mu.Lock()
-	defer m.mu.Unlock()
-	if m.m == nil {
-		m.m = make(map[T]int)
-	}
-	m.m[v]++
-}
-
-// key2 is an internal type used by Metric2.
-type key2[T1, T2 comparable] struct {
-	f1 T1
-	f2 T2
-}
-
-// Metric2 accumulates metrics of pairs of values.
-type Metric2[T1, T2 comparable] struct {
-	mu sync.Mutex
-	m  map[key2[T1, T2]]int
-}
-
-// Add adds an instance of a value pair.
-func (m *Metric2[T1, T2]) Add(v1 T1, v2 T2) {
-	m.mu.Lock()
-	defer m.mu.Unlock()
-	if m.m == nil {
-		m.m = make(map[key2[T1, T2]]int)
-	}
-	m.m[key2[T1, T2]{v1, v2}]++
-}
-
-// key3 is an internal type used by Metric3.
-type key3[T1, T2, T3 comparable] struct {
-	f1 T1
-	f2 T2
-	f3 T3
-}
-
-// Metric3 accumulates metrics of triples of values.
-type Metric3[T1, T2, T3 comparable] struct {
-	mu sync.Mutex
-	m  map[key3[T1, T2, T3]]int
-}
-
-// Add adds an instance of a value triplet.
-func (m *Metric3[T1, T2, T3]) Add(v1 T1, v2 T2, v3 T3) {
-	m.mu.Lock()
-	defer m.mu.Unlock()
-	if m.m == nil {
-		m.m = make(map[key3[T1, T2, T3]]int)
-	}
-	m.m[key3[T1, T2, T3]{v1, v2, v3}]++
-}
-
-// Repeat for the maximum number of permitted arguments.
-```
-
-Using this package looks like this:
-
-```
-import "metrics"
-
-var m = metrics.Metric2[string, int]{}
-
-func F(s string, i int) {
-	m.Add(s, i) // this call is type checked at compile time
-}
-```
-
-This implementation has a certain amount of repetition due to the lack
-of support for variadic type parameters.
-Using the package, though, is easy and type safe.
-
-### List transform
-
-While slices are efficient and easy to use, there are occasional cases
-where a linked list is appropriate.
-This example primarily shows transforming a linked list of one type to
-another type, as an example of using different instantiations of the
-same generic type.
-
-```
-// Package lists provides a linked list of any type.
-package lists
-
-// List is a linked list.
-type List[T any] struct {
-	head, tail *element[T]
-}
-
-// An element is an entry in a linked list.
-type element[T any] struct {
-	next *element[T]
-	val  T
-}
-
-// Push pushes an element to the end of the list.
-func (lst *List[T]) Push(v T) {
-	if lst.tail == nil {
-		lst.head = &element[T]{val: v}
-		lst.tail = lst.head
-	} else {
-		lst.tail.next = &element[T]{val: v }
-		lst.tail = lst.tail.next
-	}
-}
-
-// Iterator ranges over a list.
-type Iterator[T any] struct {
-	next **element[T]
-}
-
-// Range returns an Iterator starting at the head of the list.
-func (lst *List[T]) Range() *Iterator[T] {
-	return Iterator[T]{next: &lst.head}
-}
-
-// Next advances the iterator.
-// It reports whether there are more elements.
-func (it *Iterator[T]) Next() bool {
-	if *it.next == nil {
-		return false
-	}
-	it.next = &(*it.next).next
-	return true
-}
-
-// Val returns the value of the current element.
-// The bool result reports whether the value is valid.
-func (it *Iterator[T]) Val() (T, bool) {
-	if *it.next == nil {
-		var zero T
-		return zero, false
-	}
-	return (*it.next).val, true
-}
-
-// Transform runs a transform function on a list returning a new list.
-func Transform[T1, T2 any](lst *List[T1], f func(T1) T2) *List[T2] {
-	ret := &List[T2]{}
-	it := lst.Range()
-	for {
-		if v, ok := it.Val(); ok {
-			ret.Push(f(v))
-		}
-		if !it.Next() {
-			break
-		}
-	}
-	return ret
-}
-```
-
-### Dot product
-
-A generic dot product implementation that works for slices of any
-numeric type.
-
-```
-// Numeric is a constraint that matches any numeric type.
-// It would likely be in a constraints package in the standard library.
-type Numeric interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr,
-		float32, float64,
-		complex64, complex128
-}
-
-// DotProduct returns the dot product of two slices.
-// This panics if the two slices are not the same length.
-func DotProduct[T Numeric](s1, s2 []T) T {
-	if len(s1) != len(s2) {
-		panic("DotProduct: slices of unequal length")
-	}
-	var r T
-	for i := range s1 {
-		r += s1[i] * s2[i]
-	}
-	return r
-}
-```
-
-(Note: the generics implementation approach may affect whether
-`DotProduct` uses FMA, and thus what the exact results are when using
-floating point types.
-It's not clear how much of a problem this is, or whether there is any
-way to fix it.)
-
-### Absolute difference
-
-Compute the absolute difference between two numeric values, by using
-an `Abs` method.
-This uses the same `Numeric` constraint defined in the last example.
-
-This example uses more machinery than is appropriate for the simple
-case of computing the absolute difference.
-It is intended to show how the common part of algorithms can be
-factored into code that uses methods, where the exact definition of
-the methods can vary based on the kind of type being used.
-
-```
-// NumericAbs matches numeric types with an Abs method.
-type NumericAbs[T any] interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr,
-		float32, float64,
-		complex64, complex128
-	Abs() T
-}
-
-// AbsDifference computes the absolute value of the difference of
-// a and b, where the absolute value is determined by the Abs method.
-func AbsDifference[T NumericAbs](a, b T) T {
-	d := a - b
-	return d.Abs()
-}
-```
-
-We can define an `Abs` method appropriate for different numeric types.
-
-```
-// OrderedNumeric matches numeric types that support the < operator.
-type OrderedNumeric interface {
-	type int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr,
-		float32, float64
-}
-
-// Complex matches the two complex types, which do not have a < operator.
-type Complex interface {
-	type complex64, complex128
-}
-
-// OrderedAbs is a helper type that defines an Abs method for
-// ordered numeric types.
-type OrderedAbs[T OrderedNumeric] T
-
-func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
-	if a < 0 {
-		return -a
-	}
-	return a
-}
-
-// ComplexAbs is a helper type that defines an Abs method for
-// complex types.
-type ComplexAbs[T Complex] T
-
-func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
-	d := math.Hypot(float64(real(a)), float64(imag(a)))
-	return ComplexAbs[T](complex(d, 0))
-}
-```
-
-We can then define functions that do the work for the caller by
-converting to and from the types we just defined.
-
-```
-// OrderedAbsDifference returns the absolute value of the difference
-// between a and b, where a and b are of an ordered type.
-func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
-	return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
-}
-
-// ComplexAbsDifference returns the absolute value of the difference
-// between a and b, where a and b are of a complex type.
-func ComplexAbsDifference[T Complex](a, b T) T {
-	return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
-}
-```
-
-It's worth noting that this design is not powerful enough to write
-code like the following:
-
-```
-// This function is INVALID.
-func GeneralAbsDifference[T Numeric](a, b T) T {
-	switch (interface{})(a).(type) {
-	case int, int8, int16, int32, int64,
-		uint, uint8, uint16, uint32, uint64, uintptr,
-		float32, float64:
-		return OrderedAbsDifference(a, b) // INVALID
-	case complex64, complex128:
-		return ComplexAbsDifference(a, b) // INVALID
-	}
-}
-```
-
-The calls to `OrderedAbsDifference` and `ComplexAbsDifference` are
-invalid, because not all the types that implement the `Numeric`
-constraint can implement the `OrderedNumeric` or `Complex`
-constraints.
-Although the type switch means that this code would conceptually work
-at run time, there is no support for writing this code at compile
-time.
-This is another way of expressing one of the omissions listed above:
-this design does not provide for specialization.
-
-## Acknowledgements
-
-We'd like to thank many people on the Go team, many contributors to
-the Go issue tracker, and all the people who have shared their ideas
-and their feedback on earlier design drafts.
-We read all of it, and we're grateful.
-
-For this design draft in particular we received detailed feedback from
-Josh Bleecher-Snyder, Jon Bodner, Dave Cheney, Jaana Dogan, Kevin
-Gillette, Mitchell Hashimoto, Chris Hines, Bill Kennedy, Ayke van
-Laethem, Daniel Martí, Elena Morozova, Roger Peppe, and Ronna
-Steinberg.
-
-## Appendix
-
-This appendix covers various details of the design that don't seem
-significant enough to cover in earlier sections.
-
-### Generic type aliases
-
-A type alias may refer to a generic type, but the type alias may not
-have its own parameters.
-This restriction exists because it is unclear how to handle a type
-alias with type parameters that have constraints.
-
-```
-type VectorAlias = Vector
-```
-
-In this case uses of the type alias will have to provide type
-arguments appropriate for the generic type being aliased.
-
-```
-var v VectorAlias[int]
-```
-
-Type aliases may also refer to instantiated types.
-
-```
-type VectorInt = Vector[int]
-```
-
-### Instantiating a function
-
-Go normally permits you to refer to a function without passing any
-arguments, producing a value of function type.
-You may not do this with a function that has type parameters; all type
-arguments must be known at compile time.
-That said, you can instantiate the function, by passing type
-arguments, but you don't have to call the instantiation.
-This will produce a function value with no type parameters.
-
-```
-// PrintInts is type func([]int).
-var PrintInts = Print[int]
-```
-
-### Embedded type parameter
-
-When a generic type is a struct, and the type parameter is
-embedded as a field in the struct, the name of the field is the name
-of the type parameter.
-
-```
-// A Lockable is a value that may be safely simultaneously accessed
-// from multiple goroutines via the Get and Set methods.
-type Lockable[T any] struct {
-	T
-	mu sync.Mutex
-}
-
-// Get returns the value stored in a Lockable.
-func (l *Lockable[T]) Get() T {
-	l.mu.Lock()
-	defer l.mu.Unlock()
-	return l.T
-}
-
-// Set sets the value in a Lockable.
-func (l *Lockable[T]) Set(v T) {
-	l.mu.Lock()
-	defer l.mu.Unlock()
-	l.T = v
-}
-```
-
-### Embedded type parameter methods
-
-When a generic type is a struct, and the type parameter is embedded as
-a field in the struct, any methods of the type parameter's constraint
-are promoted to be methods of the struct.
-(For purposes of [selector
-resolution](https://golang.org/ref/spec#Selectors), these methods are
-treated as being at depth 0 of the type parameter, even if in the
-actual type argument the methods were themselves promoted from an
-embedded type.)
-
-```
-// NamedInt is an int with a name. The name can be any type with
-// a String method.
-type NamedInt[Name fmt.Stringer] struct {
-	Name
-	val int
-}
-
-// Name returns the name of a NamedInt.
-func (ni NamedInt[Name]) Name() string {
-	// The String method is promoted from the embedded Name.
-	return ni.String()
-}
-```
-
-### Embedded instantiated type
-
-When embedding an instantiated type, the name of the field is the name
-of type without the type arguments.
-
-```
-type S struct {
-	T[int] // field name is T
-}
-
-func F(v S) int {
-	return v.T // not v.T[int]
-}
-```
-
-### Generic types as type switch cases
-
-A generic type may be used as the type in a type assertion or as a
-case in a type switch.
-
-Here are some trivial examples:
-
-```
-func Assertion[T any](v interface{}) (T, bool) {
-	t, ok := v.(T)
-	return t, ok
-}
-
-func Switch[T any](v interface{}) (T, bool) {
-	switch v := v.(type) {
-	case T:
-		return v, true
-	default:
-		var zero T
-		return zero, false
-	}
-}
-```
-
-In a type switch, it's OK if a generic type turns out to duplicate
-some other case in the type switch.
-The first matching case is chosen.
-
-```
-func Switch2[T any](v interface{}) int {
-	switch v.(type) {
-	case T:
-		return 0
-	case string:
-		return 1
-	default:
-		return 2
-	}
-}
-
-// S2a will be set to 0.
-var S2a = Switch2[string]("a string")
-
-// S2b will be set to 1.
-var S2b = Switch2[int]("another string")
-```
-
-### Type inference for composite literals
-
-This is a feature we are not suggesting now, but could consider for
-later versions of the language.
-
-We could also consider supporting type inference for composite
-literals of generic types.
-
-```
-type Pair[T any] struct { f1, f2 T }
-var V = Pair{1, 2} // inferred as Pair(int){1, 2}
-```
-
-It's not clear how often this will arise in real code.
-
-### Type inference for generic function arguments
-
-This is a feature we are not suggesting now, but could consider for
-later versions of the language.
-
-In the following example, consider the call to `Find` in `FindClose`.
-Type inference can determine that the type argument to `Find` is `T4`,
-and from that we know that the type of the final argument must be
-`func(T4, T4) bool`, and from that we could deduce that the type
-argument to `IsClose` must also be `T4`.
-However, the type inference algorithm described earlier cannot do
-that, so we must explicitly write `IsClose[T4]`.
-
-This may seem esoteric at first, but it comes up when passing generic
-functions to generic `Map` and `Filter` functions.
-
-```
-// Differ has a Diff method that returns how different a value is.
-type Differ[T1 any] interface {
-	Diff(T1) int
-}
-
-// IsClose returns whether a and b are close together, based on Diff.
-func IsClose[T2 Differ](a, b T2) bool {
-	return a.Diff(b) < 2
-}
-
-// Find returns the index of the first element in s that matches e,
-// based on the cmp function. It returns -1 if no element matches.
-func Find[T3 any](s []T3, e T3, cmp func(a, b T3) bool) int {
-	for i, v := range s {
-		if cmp(v, e) {
-			return i
-		}
-	}
-	return -1
-}
-
-// FindClose returns the index of the first element in s that is
-// close to e, based on IsClose.
-func FindClose[T4 Differ](s []T4, e T4) int {
-	// With the current type inference algorithm we have to
-	// explicitly write IsClose[T4] here, although it
-	// is the only type argument we could possibly use.
-	return Find(s, e, IsClose[T4])
-}
-```
-
-### Reflection on type arguments
-
-Although we don't suggest changing the reflect package, one
-possibility to consider for the future would be to add two new
-methods to `reflect.Type`: `NumTypeArgument() int` would return the
-number of type arguments to a type, and `TypeArgument(i) Type` would
-return the i'th type argument.
-`NumTypeArgument` would return non-zero for an instantiated generic
-type.
-Similar methods could be defined for `reflect.Value`, for which
-`NumTypeArgument` would return non-zero for an instantiated generic
-function.
-There might be programs that care about this information.
+This draft design has [become a
+proposal](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md).