From: Robert Griesemer Date: Sat, 20 Nov 2021 22:35:02 +0000 (-0800) Subject: spec: add section on instantiation X-Git-Tag: go1.18beta1~187 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a3b8f627c258f34325d2284ce636f8d4fb103331;p=gostls13.git spec: add section on instantiation Change-Id: I2770da87b4c977b51dfa046f2f08283917675e1c Reviewed-on: https://go-review.googlesource.com/c/go/+/365916 Trust: Robert Griesemer Trust: Dan Scales Reviewed-by: Ian Lance Taylor Reviewed-by: Dan Scales --- diff --git a/doc/go_spec.html b/doc/go_spec.html index d8e6bb7b8e..6f30ed7b91 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -2913,13 +2913,19 @@ non-blank identifier denoting a or a parenthesized expression.

+

+An operand name denoting a type-parameterized function +may be followed by a list of type arguments; the +resulting operand is an instantiated function. +

+

The blank identifier may appear as an operand only on the left-hand side of an assignment.

-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 .
 

Qualified identifiers

-A qualified identifier is an identifier qualified with a package name prefix. +A qualified identifier is an identifier qualified with a package name prefix. Both the package name and the identifier must not be blank.

@@ -3962,6 +3968,11 @@ var pt *Point pt.Scale(3.5) // method call with receiver pt
+

+If f denotes a parameterized function, it must be +instantiated before it can be called. +

+

In a function call, the function value and arguments are evaluated in the usual order. @@ -4073,6 +4084,81 @@ within Greeting, who will have the same value as +

Instantiations

+ +

+A parameterized function or type is instantiated by substituting type arguments +for the type parameters. +Instantiation proceeds in two phases: +

+ +
    +
  1. +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. +
  2. + +
  3. +After substitution, each type argument must implement +the constraint (instantiated, if necessary) +of the corresponding type parameter. Otherwise instantiation fails. +
  4. +
+ +

+Instantiating a type results in a new non-parameterized named type; +instantiating a function produces a new non-parameterized function. +

+ +
+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
+
+ +

+Type arguments may be provided explicitly, or they may be partially or completely +inferred. +A partially provided type argument list cannot be empty; there must be at least the +first argument. +

+ +
+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
+
+ +

+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". +

+ +

+Parameterized types, and parameterized functions that are not called, +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. +

+ +
+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
+

Operators