mirror of
https://github.com/golang/go
synced 2024-11-02 13:42:29 +00:00
spec: add type parameter lists
Change-Id: I29e9188a0fa1326c2755a9b86aeb47feaa8019be Reviewed-on: https://go-review.googlesource.com/c/go/+/365274 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
91abe4be0e
commit
0c3b4a358a
1 changed files with 176 additions and 21 deletions
197
doc/go_spec.html
197
doc/go_spec.html
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification - Go 1.18 Draft (incomplete)",
|
"Title": "The Go Programming Language Specification - Go 1.18 Draft (incomplete)",
|
||||||
"Subtitle": "Version of Nov 18, 2021",
|
"Subtitle": "Version of Nov 19, 2021",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
@ -849,8 +849,7 @@ Every type has a (possibly empty) method set associated with it:
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
The method set of a <a href="#Pointer_types">pointer</a> <code>*T</code>
|
The method set of a pointer to a defined type <code>T</code>
|
||||||
to a defined type <code>T</code>
|
|
||||||
(where <code>T</code> is neither a pointer nor an interface)
|
(where <code>T</code> is neither a pointer nor an interface)
|
||||||
is the set of all methods declared with receiver <code>*T</code> or <code>T</code>.
|
is the set of all methods declared with receiver <code>*T</code> or <code>T</code>.
|
||||||
</li>
|
</li>
|
||||||
|
@ -2246,12 +2245,12 @@ type (
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A type definition creates a new, distinct type with the same
|
A type definition creates a new, distinct type with the same
|
||||||
<a href="#Types">underlying type</a> and operations as the given type,
|
<a href="#Types">underlying type</a> and operations as the given type
|
||||||
and binds an identifier to it.
|
and binds an identifier, the <i>type name</i>, to it.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="ebnf">
|
<pre class="ebnf">
|
||||||
TypeDef = identifier Type .
|
TypeDef = identifier [ TypeParameters ] Type .
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -2328,6 +2327,130 @@ func (tz TimeZone) String() string {
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If the type definition specifies <a href="#Type_parameter_lists">type parameters</a>,
|
||||||
|
the type name denotes a <i>parameterized type</i>.
|
||||||
|
Parameterized types must be <a href="#Instantiations">instantiated</a> when they
|
||||||
|
are used.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
type List[T any] struct {
|
||||||
|
next *List[T]
|
||||||
|
value T
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tree[T constraints.Ordered] struct {
|
||||||
|
left, right *Tree[T]
|
||||||
|
value T
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The given type cannot be a type parameter in a type definition.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
// The method Len returns the number of elements in the linked list l.
|
||||||
|
func (l *List[T]) Len() int { … }
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h3 id="Type_parameter_lists">Type parameter lists</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A type parameter list declares the <a href="#Type_parameters">type parameters</a>
|
||||||
|
in a type-parameterized function or type declaration.
|
||||||
|
The type parameter list looks like an ordinary <a href="#Function_types">function parameter list</a>
|
||||||
|
except that the type parameter names must all be present and the list is enclosed
|
||||||
|
in square brackets rather than parentheses.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre class="ebnf">
|
||||||
|
TypeParameters = "[" TypeParamList [ "," ] "]" .
|
||||||
|
TypeParamList = TypeParamDecl { "," TypeParamDecl } .
|
||||||
|
TypeParamDecl = IdentifierList TypeConstraint .
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Each identifier declares a type parameter.
|
||||||
|
All non-blank names in the list must be unique.
|
||||||
|
Each type parameter is a new and different <a href="#Types">named type</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
[P any]
|
||||||
|
[S interface{ ~[]byte|string }]
|
||||||
|
[S ~[]E, E any]
|
||||||
|
[P Constraint[int]]
|
||||||
|
[_ any]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Just as each ordinary function parameter has a parameter type, each type parameter
|
||||||
|
has a corresponding (meta-)type which is called its
|
||||||
|
<a href="#Type_constraints"><i>type constraint</i></a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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 <code>*C</code>
|
||||||
|
or <code>(C)</code>:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
type T[P *C] …
|
||||||
|
type T[P (C)] …
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In these rare cases, the type parameter declaration is indistinguishable from
|
||||||
|
the expressions <code>P*C</code> or <code>P(C)</code> and the type declaration
|
||||||
|
is parsed as an array type declaration.
|
||||||
|
To resolve the ambiguity, embed the constraint in an interface:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
type T[P interface{*C}] …
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h4 id="Type_constraints">Type constraints</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A type constraint is an <a href="#Interface_types">interface</a> that determines the
|
||||||
|
set of permissible type arguments for the respective type parameter and controls the
|
||||||
|
operations supported by values of that type parameter.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre class="ebnf">
|
||||||
|
TypeConstraint = TypeElem .
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If the constraint is an interface literal containing exactly one embedded type element
|
||||||
|
<code>interface{E}</code>, in a type parameter list the enclosing <code>interface{ … }</code>
|
||||||
|
may be omitted for convenience:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
[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
|
||||||
|
</pre>
|
||||||
|
|
||||||
<h3 id="Variable_declarations">Variable declarations</h3>
|
<h3 id="Variable_declarations">Variable declarations</h3>
|
||||||
|
|
||||||
|
@ -2437,13 +2560,19 @@ they can be used to declare local temporary variables.
|
||||||
|
|
||||||
<h3 id="Function_declarations">Function declarations</h3>
|
<h3 id="Function_declarations">Function declarations</h3>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Given the importance of functions, this section has always
|
||||||
|
been woefully underdeveloped. Would be nice to expand this
|
||||||
|
a bit.
|
||||||
|
-->
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A function declaration binds an identifier, the <i>function name</i>,
|
A function declaration binds an identifier, the <i>function name</i>,
|
||||||
to a function.
|
to a function.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="ebnf">
|
<pre class="ebnf">
|
||||||
FunctionDecl = "func" FunctionName Signature [ FunctionBody ] .
|
FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] .
|
||||||
FunctionName = identifier .
|
FunctionName = identifier .
|
||||||
FunctionBody = Block .
|
FunctionBody = Block .
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -2466,18 +2595,28 @@ func IndexRune(s string, r rune) int {
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A function declaration may omit the body. Such a declaration provides the
|
If the function declaration specifies <a href="#Type_parameter_lists">type parameters</a>,
|
||||||
signature for a function implemented outside Go, such as an assembly routine.
|
the function name denotes a <i>type-parameterized function</i>.
|
||||||
|
Type-parameterized functions must be <a href="#Instantiations">instantiated</a> when they
|
||||||
|
are used.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func min(x int, y int) int {
|
func min[T constraints.Ordered](x, y T) T {
|
||||||
if x < y {
|
if x < y {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
return y
|
return y
|
||||||
}
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
func flushICache(begin, end uintptr) // implemented externally
|
func flushICache(begin, end uintptr) // implemented externally
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
@ -2498,9 +2637,10 @@ Receiver = Parameters .
|
||||||
The receiver is specified via an extra parameter section preceding the method
|
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.
|
name. That parameter section must declare a single non-variadic parameter, the receiver.
|
||||||
Its type must be a <a href="#Type_definitions">defined</a> type <code>T</code> or a
|
Its type must be a <a href="#Type_definitions">defined</a> type <code>T</code> or a
|
||||||
pointer to a defined type <code>T</code>. <code>T</code> is called the receiver
|
pointer to a defined type <code>T</code>, possibly followed by a list of type parameter
|
||||||
<i>base type</i>. A receiver base type cannot be a pointer or interface type and
|
names <code>[P1, P2, …]</code> enclosed in square brackets.
|
||||||
it must be defined in the same package as the method.
|
<code>T</code> is called the receiver <i>base type</i>. 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 <i>bound</i> to its receiver base type and the method name
|
The method is said to be <i>bound</i> to its receiver base type and the method name
|
||||||
is visible only within <a href="#Selectors">selectors</a> for type <code>T</code>
|
is visible only within <a href="#Selectors">selectors</a> for type <code>T</code>
|
||||||
or <code>*T</code>.
|
or <code>*T</code>.
|
||||||
|
@ -2542,19 +2682,33 @@ to the base type <code>Point</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The type of a method is the type of a function with the receiver as first
|
If the receiver base type is a <a href="#Type_declarations">parameterized type</a>, the
|
||||||
argument. For instance, the method <code>Scale</code> has type
|
receiver specification must declare corresponding type parameters for the method
|
||||||
|
to use. This makes the receiver type parameters available to the method.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Syntactically, this type parameter declaration looks like an
|
||||||
|
<a href="#Instantiantions">instantiation</a> 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.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
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 }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
|
||||||
However, a function declared this way is not a method.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Expressions">Expressions</h2>
|
<h2 id="Expressions">Expressions</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -2823,6 +2977,7 @@ noteFrequency := map[string]float32{
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A function literal represents an anonymous <a href="#Function_declarations">function</a>.
|
A function literal represents an anonymous <a href="#Function_declarations">function</a>.
|
||||||
|
Function literals cannot declare type parameters.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="ebnf">
|
<pre class="ebnf">
|
||||||
|
|
Loading…
Reference in a new issue