diff --git a/doc/go_spec.html b/doc/go_spec.html index 7c53a1eb91..0ce6a3ca18 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -849,8 +849,7 @@ Every type has a (possibly empty) method set associated with it:
  • -The method set of a pointer *T -to a defined type T +The method set of a pointer to a defined type T (where T is neither a pointer nor an interface) is the set of all methods declared with receiver *T or T.
  • @@ -2246,12 +2245,12 @@ type (

    A type definition creates a new, distinct type with the same -underlying type and operations as the given type, -and binds an identifier to it. +underlying type and operations as the given type +and binds an identifier, the type name, to it.

    -TypeDef = identifier Type .
    +TypeDef = identifier [ TypeParameters ] Type .
     

    @@ -2328,6 +2327,130 @@ func (tz TimeZone) String() string { } +

    +If the type definition specifies type parameters, +the type name denotes a parameterized type. +Parameterized types must be instantiated when they +are used. +

    + +
    +type List[T any] struct {
    +	next  *List[T]
    +	value T
    +}
    +
    +type Tree[T constraints.Ordered] struct {
    +	left, right *Tree[T]
    +	value       T
    +}
    +
    + +

    +The given type cannot be a type parameter in a type definition. +

    + +
    +type T[P any] P    // illegal: P is a type parameter
    +
    +func f[T any]() {
    +	type L T   // illegal: T is a type parameter declared by the enclosing function
    +}
    +
    + +

    +A parameterized type may also have methods associated with it. In this case, +the method receivers must declare the same number of type parameters as +present in the parameterized type definition. +

    + +
    +// The method Len returns the number of elements in the linked list l.
    +func (l *List[T]) Len() int  { … }
    +
    + +

    Type parameter lists

    + +

    +A type parameter list declares the type parameters +in a type-parameterized function or type declaration. +The type parameter list looks like an ordinary function parameter list +except that the type parameter names must all be present and the list is enclosed +in square brackets rather than parentheses. +

    + +
    +TypeParameters  = "[" TypeParamList [ "," ] "]" .
    +TypeParamList   = TypeParamDecl { "," TypeParamDecl } .
    +TypeParamDecl   = IdentifierList TypeConstraint .
    +
    + +

    +Each identifier declares a type parameter. +All non-blank names in the list must be unique. +Each type parameter is a new and different named type. +

    + +
    +[P any]
    +[S interface{ ~[]byte|string }]
    +[S ~[]E, E any]
    +[P Constraint[int]]
    +[_ any]
    +
    + +

    +Just as each ordinary function parameter has a parameter type, each type parameter +has a corresponding (meta-)type which is called its +type constraint. +

    + +

    +A parsing ambiguity arises when the type parameter list for a parameterized type +declares a single type parameter with a type constraint of the form *C +or (C): +

    + +
    +type T[P *C] …
    +type T[P (C)] …
    +
    + +

    +In these rare cases, the type parameter declaration is indistinguishable from +the expressions P*C or P(C) and the type declaration +is parsed as an array type declaration. +To resolve the ambiguity, embed the constraint in an interface: +

    + +
    +type T[P interface{*C}] …
    +
    + +

    Type constraints

    + +

    +A type constraint is an interface that determines the +set of permissible type arguments for the respective type parameter and controls the +operations supported by values of that type parameter. +

    + +
    +TypeConstraint = TypeElem .
    +
    + +

    +If the constraint is an interface literal containing exactly one embedded type element +interface{E}, in a type parameter list the enclosing interface{ … } +may be omitted for convenience: +

    + +
    +[T *P]                             // = [T interface{*P}]
    +[T ~int]                           // = [T interface{~int}]
    +[T int|string]                     // = [T interface{int|string}]
    +type Constraint ~int               // illegal: ~int is not inside a type parameter list
    +

    Variable declarations

    @@ -2437,13 +2560,19 @@ they can be used to declare local temporary variables.

    Function declarations

    + +

    A function declaration binds an identifier, the function name, to a function.

    -FunctionDecl = "func" FunctionName Signature [ FunctionBody ] .
    +FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] .
     FunctionName = identifier .
     FunctionBody = Block .
     
    @@ -2466,18 +2595,28 @@ func IndexRune(s string, r rune) int {

    -A function declaration may omit the body. Such a declaration provides the -signature for a function implemented outside Go, such as an assembly routine. +If the function declaration specifies type parameters, +the function name denotes a type-parameterized function. +Type-parameterized functions must be instantiated when they +are used.

    -func min(x int, y int) int {
    +func min[T constraints.Ordered](x, y T) T {
     	if x < y {
     		return x
     	}
     	return y
     }
    +
    +

    +A function declaration without type parameters may omit the body. +Such a declaration provides the signature for a function implemented outside Go, +such as an assembly routine. +

    + +
     func flushICache(begin, end uintptr)  // implemented externally
     
    @@ -2498,9 +2637,10 @@ Receiver = Parameters . The receiver is specified via an extra parameter section preceding the method name. That parameter section must declare a single non-variadic parameter, the receiver. Its type must be a defined type T or a -pointer to a defined type T. T is called the receiver -base type. A receiver base type cannot be a pointer or interface type and -it must be defined in the same package as the method. +pointer to a defined type T, possibly followed by a list of type parameter +names [P1, P2, …] enclosed in square brackets. +T is called the receiver base type. A receiver base type cannot be +a pointer or interface type and it must be defined in the same package as the method. The method is said to be bound to its receiver base type and the method name is visible only within selectors for type T or *T. @@ -2542,19 +2682,33 @@ to the base type Point.

    -The type of a method is the type of a function with the receiver as first -argument. For instance, the method Scale has type +If the receiver base type is a parameterized type, the +receiver specification must declare corresponding type parameters for the method +to use. This makes the receiver type parameters available to the method. +

    + +

    +Syntactically, this type parameter declaration looks like an +instantiation of the receiver base type, except that +the type arguments are the type parameters being declared, one for each type parameter +of the receiver base type. +The type parameter names do not need to match their corresponding parameter names in the +receiver base type definition, and all non-blank parameter names must be unique in the +receiver parameter section and the method signature. +The receiver type parameter constraints are implied by the receiver base type definition: +corresponding type parameters have corresponding constraints.

    -func(p *Point, factor float64)
    +type Pair[A, B any] struct {
    +	a A
    +	b B
    +}
    +
    +func (p Pair[A, B]) Swap() Pair[A, B]  { return Pair[A, B]{p.b, p.a} }
    +func (p Pair[First, _]) First() First  { return p.a }
     
    -

    -However, a function declared this way is not a method. -

    - -

    Expressions

    @@ -2823,6 +2977,7 @@ noteFrequency := map[string]float32{

    A function literal represents an anonymous function. +Function literals cannot declare type parameters.