mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
spec: add section on instantiation
Change-Id: I2770da87b4c977b51dfa046f2f08283917675e1c Reviewed-on: https://go-review.googlesource.com/c/go/+/365916 Trust: Robert Griesemer <gri@golang.org> Trust: Dan Scales <danscales@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
parent
ce2a20af46
commit
a3b8f627c2
|
@ -2913,13 +2913,19 @@ non-<a href="#Blank_identifier">blank</a> identifier denoting a
|
|||
or a parenthesized expression.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An operand name denoting a <a href="#Function_declarations">type-parameterized function</a>
|
||||
may be followed by a list of <a href="#Type_arguments">type arguments</a>; the
|
||||
resulting operand is an <a href="#Instantiations">instantiated</a> function.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="#Blank_identifier">blank identifier</a> may appear as an
|
||||
operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
Operand = Literal | OperandName | "(" Expression ")" .
|
||||
Operand = Literal | OperandName [ TypeArgs ] | "(" Expression ")" .
|
||||
Literal = BasicLit | CompositeLit | FunctionLit .
|
||||
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
|
||||
OperandName = identifier | QualifiedIdent .
|
||||
|
@ -2928,7 +2934,7 @@ OperandName = identifier | QualifiedIdent .
|
|||
<h3 id="Qualified_identifiers">Qualified identifiers</h3>
|
||||
|
||||
<p>
|
||||
A qualified identifier is an identifier qualified with a package name prefix.
|
||||
A <i>qualified identifier</i> is an identifier qualified with a package name prefix.
|
||||
Both the package name and the identifier must not be
|
||||
<a href="#Blank_identifier">blank</a>.
|
||||
</p>
|
||||
|
@ -3962,6 +3968,11 @@ var pt *Point
|
|||
pt.Scale(3.5) // method call with receiver pt
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If <code>f</code> denotes a parameterized function, it must be
|
||||
<a href="#Instantiations">instantiated</a> before it can be called.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In a function call, the function value and arguments are evaluated in
|
||||
<a href="#Order_of_evaluation">the usual order</a>.
|
||||
|
@ -4073,6 +4084,81 @@ within <code>Greeting</code>, <code>who</code> will have the same value as <code
|
|||
with the same underlying array.
|
||||
</p>
|
||||
|
||||
<h3 id="Instantiations">Instantiations</h3>
|
||||
|
||||
<p>
|
||||
A parameterized function or type is <i>instantiated</i> by substituting type arguments
|
||||
for the type parameters.
|
||||
Instantiation proceeds in two phases:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
Each type argument is substituted for its corresponding type parameter in the parameterized
|
||||
declaration.
|
||||
This substitution happens across the entire function or type declaration,
|
||||
including the type parameter list itself and any types in that list.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
After substitution, each type argument must <a href="#Interface_types">implement</a>
|
||||
the <a href="#Type_parameter_lists">constraint</a> (instantiated, if necessary)
|
||||
of the corresponding type parameter. Otherwise instantiation fails.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Instantiating a type results in a new non-parameterized <a href="#Types">named type</a>;
|
||||
instantiating a function produces a new non-parameterized function.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type parameter list type arguments after substitution
|
||||
|
||||
[P any] int [int any]
|
||||
[S ~[]E, E any] []int, int [[]int ~[]int, int any]
|
||||
[P io.Writer] string [string io.Writer] // illegal: string doesn't implement io.Writer
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Type arguments may be provided explicitly, or they may be partially or completely
|
||||
<a href="#Type_inference">inferred</a>.
|
||||
A partially provided type argument list cannot be empty; there must be at least the
|
||||
first argument.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type T[P1 ~int, P2 ~[]P1] struct{ … }
|
||||
|
||||
T[] // illegal: at least the first type argument must be present, even if it could be inferred
|
||||
T[int] // argument for P1 explicitly provided, argument for P2 inferred
|
||||
T[int, []int] // both arguments explicitly provided
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A partial type argument list specifies a prefix of the full list of type arguments, leaving
|
||||
the remaining arguments to be inferred. Loosely speaking, type arguments may be omitted from
|
||||
"right to left".
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Parameterized types, and parameterized functions that are not <a href="#Calls">called</a>,
|
||||
require a type argument list for instantiation; if the list is partial, all
|
||||
remaining type arguments must be inferrable.
|
||||
Calls to parameterized functions may provide a (possibly partial) type
|
||||
argument list, or may omit it entirely if the omitted type arguments are
|
||||
inferrable from the ordinary (non-type) function arguments.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func min[T constraints.Ordered](x, y T) T { … }
|
||||
|
||||
f := min // illegal: min must be instantiated when used without being called
|
||||
minInt := min[int] // minInt has type func(x, y int) int
|
||||
a := minInt(2, 3) // a has value 2 of type int
|
||||
b := min[float64](2.0, 3) // b has value 2.0 of type float64
|
||||
c := min(b, -1) // c has value -1.0 of type float64
|
||||
</pre>
|
||||
|
||||
<h3 id="Operators">Operators</h3>
|
||||
|
||||
|
|
Loading…
Reference in a new issue