]> Cypherpunks.ru repositories - gostls13.git/blobdiff - doc/go_spec.html
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / doc / go_spec.html
index bb5b2f3db9e38a8f185225191d06ccf8037adc0c..18f88d5eadef99afc2e6f9ff9bb8784fb007dba3 100644 (file)
@@ -1,6 +1,6 @@
 <!--{
        "Title": "The Go Programming Language Specification",
-       "Subtitle": "Version of June 13, 2023",
+       "Subtitle": "Version of Nov 1, 2023",
        "Path": "/ref/spec"
 }-->
 
@@ -884,7 +884,7 @@ are required when different numeric types are mixed in an expression
 or assignment. For instance, <code>int32</code> and <code>int</code>
 are not the same type even though they may have the same size on a
 particular architecture.
-
+</p>
 
 <h3 id="String_types">String types</h3>
 
@@ -2511,7 +2511,7 @@ type (
 
 <p>
 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="#Underlying_types">underlying type</a> and operations as the given type
 and binds an identifier, the <i>type name</i>, to it.
 </p>
 
@@ -3910,7 +3910,7 @@ For <code>a</code> of <a href="#Type_parameter_declarations">type parameter type
            that <code>P</code> is instantiated with, and the type of <code>a[x]</code> is
            the type of the (identical) element types.</li>
        <li><code>a[x]</code> may not be assigned to if <code>P</code>'s type set
-           includes string types.
+           includes string types.</li>
 </ul>
 
 <p>
@@ -4340,24 +4340,46 @@ type parameter list    type arguments    after substitution
 </pre>
 
 <p>
-For a generic function, type arguments may be provided explicitly, or they
-may be partially or completely <a href="#Type_inference">inferred</a>.
-A generic function that is <i>not</i> <a href="#Calls">called</a> requires a
-type argument list for instantiation; if the list is partial, all
-remaining type arguments must be inferrable.
-A generic function that is called 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.
+When using a generic function, type arguments may be provided explicitly,
+or they may be partially or completely <a href="#Type_inference">inferred</a>
+from the context in which the function is used.
+Provided that they can be inferred, type argument lists may be omitted entirely if the function is:
+</p>
+
+<ul>
+<li>
+       <a href="#Calls">called</a> with ordinary arguments,
+</li>
+<li>
+       <a href="#Assignment_statements">assigned</a> to a variable with a known type
+</li>
+<li>
+       <a href="#Calls">passed as an argument</a> to another function, or
+</li>
+<li>
+       <a href="#Return_statements">returned as a result</a>.
+</li>
+</ul>
+
+<p>
+In all other cases, a (possibly partial) type argument list must be present.
+If a type argument list is absent or partial, all missing type arguments
+must be inferrable from the context in which the function is used.
 </p>
 
 <pre>
-func min[T ~int|~float64](x, y T) T { … }
+// sum returns the sum (concatenation, for strings) of its arguments.
+func sum[T ~int | ~float64 | ~string](x... T) T { … }
 
-f := min                   // illegal: min must be instantiated with type arguments 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
+x := sum                       // illegal: the type of x is unknown
+intSum := sum[int]             // intSum has type func(x... int) int
+a := intSum(2, 3)              // a has value 5 of type int
+b := sum[float64](2.0, 3)      // b has value 5.0 of type float64
+c := sum(b, -1)                // c has value 4.0 of type float64
+
+type sumFunc func(x... string) string
+var f sumFunc = sum            // same as var f sumFunc = sum[string]
+f = sum                        // same as f = sum[string]
 </pre>
 
 <p>
@@ -4384,402 +4406,323 @@ For a generic type, all type arguments must always be provided explicitly.
 <h3 id="Type_inference">Type inference</h3>
 
 <p>
-<em>NOTE: This section is not yet up-to-date for Go 1.21.</em>
-</p>
-
-<p>
-Missing function type arguments may be <i>inferred</i> by a series of steps, described below.
-Each step attempts to use known information to infer additional type arguments.
-Type inference stops as soon as all type arguments are known.
-After type inference is complete, it is still necessary to substitute all type arguments
-for type parameters and verify that each type argument
-<a href="#Implementing_an_interface">implements</a> the relevant constraint;
-it is possible for an inferred type argument to fail to implement a constraint, in which
-case instantiation fails.
-</p>
-
-<p>
-Type inference is based on
-</p>
-
-<ul>
-<li>
-       a <a href="#Type_parameter_declarations">type parameter list</a>
-</li>
-<li>
-       a substitution map <i>M</i> initialized with the known type arguments, if any
-</li>
-<li>
-       a (possibly empty) list of ordinary function arguments (in case of a function call only)
-</li>
-</ul>
-
-<p>
-and then proceeds with the following steps:
-</p>
-
-<ol>
-<li>
-       apply <a href="#Function_argument_type_inference"><i>function argument type inference</i></a>
-       to all <i>typed</i> ordinary function arguments
-</li>
-<li>
-       apply <a href="#Constraint_type_inference"><i>constraint type inference</i></a>
-</li>
-<li>
-       apply function argument type inference to all <i>untyped</i> ordinary function arguments
-       using the default type for each of the untyped function arguments
-</li>
-<li>
-       apply constraint type inference
-</li>
-</ol>
-
-<p>
-If there are no ordinary or untyped function arguments, the respective steps are skipped.
-Constraint type inference is skipped if the previous step didn't infer any new type arguments,
-but it is run at least once if there are missing type arguments.
-</p>
-
-<p>
-The substitution map <i>M</i> is carried through all steps, and each step may add entries to <i>M</i>.
-The process stops as soon as <i>M</i> has a type argument for each type parameter or if an inference step fails.
-If an inference step fails, or if <i>M</i> is still missing type arguments after the last step, type inference fails.
-</p>
-
-<h4 id="Type_unification">Type unification</h4>
-
-<p>
-Type inference is based on <i>type unification</i>. A single unification step
-applies to a <a href="#Type_inference">substitution map</a> and two types, either
-or both of which may be or contain type parameters. The substitution map tracks
-the known (explicitly provided or already inferred) type arguments: the map
-contains an entry <code>P</code> &RightArrow; <code>A</code> for each type
-parameter <code>P</code> and corresponding known type argument <code>A</code>.
-During unification, known type arguments take the place of their corresponding type
-parameters when comparing types. Unification is the process of finding substitution
-map entries that make the two types equivalent.
-</p>
-
-<p>
-For unification, two types that don't contain any type parameters from the current type
-parameter list are <i>equivalent</i>
-if they are identical, or if they are channel types that are identical ignoring channel
-direction, or if their underlying types are equivalent.
+A use of a generic function may omit some or all type arguments if they can be
+<i>inferred</i> from the context within which the function is used, including
+the constraints of the function's type parameters.
+Type inference succeeds if it can infer the missing type arguments
+and <a href="#Instantiations">instantiation</a> succeeds with the
+inferred type arguments.
+Otherwise, type inference fails and the program is invalid.
 </p>
 
 <p>
-Unification works by comparing the structure of pairs of 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;
-each successful match causes an entry to be added to the substitution map.
-If the structure differs, or types other than type parameters are not equivalent,
-unification fails.
+Type inference uses the type relationships between pairs of types for inference:
+For instance, a function argument must be <a href="#Assignability">assignable</a>
+to its respective function parameter; this establishes a relationship between the
+type of the argument and the type of the parameter.
+If either of these two types contains type parameters, type inference looks for the
+type arguments to substitute the type parameters with such that the assignability
+relationship is satisfied.
+Similarly, type inference uses the fact that a type argument must
+<a href="#Satisfying_a_type_constraint">satisfy</a> the constraint of its respective
+type parameter.
 </p>
 
-<!--
-TODO(gri) Somewhere we need to describe the process of adding an entry to the
-          substitution map: if the entry is already present, the type argument
-         values are themselves unified.
--->
-
 <p>
-For example, if <code>T1</code> and <code>T2</code> are type parameters,
-<code>[]map[int]bool</code> can be unified with any of the following:
+Each such pair of matched types corresponds to a <i>type equation</i> containing
+one or multiple type parameters, from one or possibly multiple generic functions.
+Inferring the missing type arguments means solving the resulting set of type
+equations for the respective type parameters.
 </p>
 
-<pre>
-[]map[int]bool   // types are identical
-T1               // adds T1 &RightArrow; []map[int]bool to substitution map
-[]T1             // adds T1 &RightArrow; map[int]bool to substitution map
-[]map[T1]T2      // adds T1 &RightArrow; int and T2 &RightArrow; bool to substitution map
-</pre>
-
 <p>
-On the other hand, <code>[]map[int]bool</code> cannot be unified with any of
+For example, given
 </p>
 
 <pre>
-int              // int is not a slice
-struct{}         // a struct is not a slice
-[]struct{}       // a struct is not a map
-[]map[T1]string  // map element types don't match
-</pre>
-
-<p>
-As an exception to this general rule, because a <a href="#Type_definitions">defined type</a>
-<code>D</code> and a type literal <code>L</code> are never equivalent,
-unification compares the underlying type of <code>D</code> with <code>L</code> instead.
-For example, given the defined type
-</p>
+// dedup returns a copy of the argument slice with any duplicate entries removed.
+func dedup[S ~[]E, E comparable](S) S { … }
 
-<pre>
-type Vector []float64
+type Slice []int
+var s Slice
+s = dedup(s)   // same as s = dedup[Slice, int](s)
 </pre>
 
 <p>
-and the type literal <code>[]E</code>, unification compares <code>[]float64</code> with
-<code>[]E</code> and adds an entry <code>E</code> &RightArrow; <code>float64</code> to
-the substitution map.
-</p>
-
-<h4 id="Function_argument_type_inference">Function argument type inference</h4>
-
-<!-- In this section and the section on constraint type inference we start with examples
-rather than have the examples follow the rules as is customary elsewhere in spec.
-Hopefully this helps building an intuition and makes the rules easier to follow. -->
-
-<p>
-Function argument type inference infers type arguments from function arguments:
-if a function parameter is declared with a type <code>T</code> that uses
-type parameters,
-<a href="#Type_unification">unifying</a> the type of the corresponding
-function argument with <code>T</code> may infer type arguments for the type
-parameters used by <code>T</code>.
-</p>
-
-<p>
-For instance, given the generic function
+the variable <code>s</code> of type <code>Slice</code> must be assignable to
+the function parameter type <code>S</code> for the program to be valid.
+To reduce complexity, type inference ignores the directionality of assignments,
+so the type relationship between <code>Slice</code> and <code>S</code> can be
+expressed via the (symmetric) type equation <code>Slice ≡<sub>A</sub> S</code>
+(or <code>S ≡<sub>A</sub> Slice</code> for that matter),
+where the <code><sub>A</sub></code> in <code>≡<sub>A</sub></code>
+indicates that the LHS and RHS types must match per assignability rules
+(see the section on <a href="#Type_unification">type unification</a> for
+details).
+Similarly, the type parameter <code>S</code> must satisfy its constraint
+<code>~[]E</code>. This can be expressed as <code>S ≡<sub>C</sub> ~[]E</code>
+where <code>X ≡<sub>C</sub> Y</code> stands for
+"<code>X</code> satisfies constraint <code>Y</code>".
+These observations lead to a set of two equations
 </p>
 
 <pre>
-func scale[Number ~int64|~float64|~complex128](v []Number, s Number) []Number
+       Slice ≡<sub>A</sub> S      (1)
+       S     ≡<sub>C</sub> ~[]E   (2)
 </pre>
 
 <p>
-and the call
+which now can be solved for the type parameters <code>S</code> and <code>E</code>.
+From (1) a compiler can infer that the type argument for <code>S</code> is <code>Slice</code>.
+Similarly, because the underlying type of <code>Slice</code> is <code>[]int</code>
+and <code>[]int</code> must match <code>[]E</code> of the constraint,
+a compiler can infer that <code>E</code> must be <code>int</code>.
+Thus, for these two equations, type inference infers
 </p>
 
 <pre>
-var vector []float64
-scaledVector := scale(vector, 42)
+       S ➞ Slice
+       E ➞ int
 </pre>
 
 <p>
-the type argument for <code>Number</code> can be inferred from the function argument
-<code>vector</code> by unifying the type of <code>vector</code> with the corresponding
-parameter type: <code>[]float64</code> and <code>[]Number</code>
-match in structure and <code>float64</code> matches with <code>Number</code>.
-This adds the entry <code>Number</code> &RightArrow; <code>float64</code> to the
-<a href="#Type_unification">substitution map</a>.
-Untyped arguments, such as the second function argument <code>42</code> here, are ignored
-in the first round of function argument type inference and only considered if there are
-unresolved type parameters left.
+Given a set of type equations, the type parameters to solve for are
+the type parameters of the functions that need to be instantiated
+and for which no explicit type arguments is provided.
+These type parameters are called <i>bound</i> type parameters.
+For instance, in the <code>dedup</code> example above, the type parameters
+<code>S</code> and <code>E</code> are bound to <code>dedup</code>.
+An argument to a generic function call may be a generic function itself.
+The type parameters of that function are included in the set of bound
+type parameters.
+The types of function arguments may contain type parameters from other
+functions (such as a generic function enclosing a function call).
+Those type parameters may also appear in type equations but they are
+not bound in that context.
+Type equations are always solved for the bound type parameters only.
 </p>
 
 <p>
-Inference happens in two separate phases; each phase operates on a specific list of
-(parameter, argument) pairs:
+Type inference supports calls of generic functions and assignments
+of generic functions to (explicitly function-typed) variables.
+This includes passing generic functions as arguments to other
+(possibly also generic) functions, and returning generic functions
+as results.
+Type inference operates on a set of equations specific to each of
+these cases.
+The equations are as follows (type argument lists are omitted for clarity):
 </p>
 
-<ol>
+<ul>
 <li>
-       The list <i>Lt</i> contains all (parameter, argument) pairs where the parameter
-       type uses type parameters and where the function argument is <i>typed</i>.
+       <p>
+       For a function call <code>f(a<sub>0</sub>, a<sub>1</sub>, …)</code> where
+       <code>f</code> or a function argument <code>a<sub>i</sub></code> is
+       a generic function:
+       <br>
+       Each pair <code>(a<sub>i</sub>, p<sub>i</sub>)</code> of corresponding
+       function arguments and parameters where <code>a<sub>i</sub></code> is not an
+       <a href="#Constants">untyped constant</a> yields an equation
+       <code>typeof(p<sub>i</sub>) ≡<sub>A</sub> typeof(a<sub>i</sub>)</code>.
+       <br>
+       If <code>a<sub>i</sub></code> is an untyped constant <code>c<sub>j</sub></code>,
+       and <code>typeof(p<sub>i</sub>)</code> is a bound type parameter <code>P<sub>k</sub></code>,
+       the pair <code>(c<sub>j</sub>, P<sub>k</sub>)</code> is collected separately from
+       the type equations.
+       </p>
 </li>
 <li>
-       The list <i>Lu</i> contains all remaining pairs where the parameter type is a single
-       type parameter. In this list, the respective function arguments are untyped.
+       <p>
+       For an assignment <code>v = f</code> of a generic function <code>f</code> to a
+       (non-generic) variable <code>v</code> of function type:
+       <br>
+       <code>typeof(v) ≡<sub>A</sub> typeof(f)</code>.
+       </p>
 </li>
-</ol>
-
-<p>
-Any other (parameter, argument) pair is ignored.
-</p>
+<li>
+       <p>
+       For a return statement <code>return …, f, … </code> where <code>f</code> is a
+       generic function returned as a result to a (non-generic) result variable
+       <code>r</code> of function type:
+       <br>
+       <code>typeof(r) ≡<sub>A</sub> typeof(f)</code>.
+       </p>
+</li>
+</ul>
 
 <p>
-By construction, the arguments of the pairs in <i>Lu</i> are <i>untyped</i> constants
-(or the untyped boolean result of a comparison). And because <a href="#Constants">default types</a>
-of untyped values are always predeclared non-composite types, they can never match against
-a composite type, so it is sufficient to only consider parameter types that are single type
-parameters.
+Additionally, each type parameter <code>P<sub>k</sub></code> and corresponding type constraint
+<code>C<sub>k</sub></code> yields the type equation
+<code>P<sub>k</sub> ≡<sub>C</sub> C<sub>k</sub></code>.
 </p>
 
 <p>
-Each list is processed in a separate phase:
+Type inference gives precedence to type information obtained from typed operands
+before considering untyped constants.
+Therefore, inference proceeds in two phases:
 </p>
 
 <ol>
 <li>
-       In the first phase, the parameter and argument types of each pair in <i>Lt</i>
-       are unified. If unification succeeds for a pair, it may yield new entries that
-       are added to the substitution map <i>M</i>. If unification fails, type inference
-       fails.
+       <p>
+       The type equations are solved for the bound
+       type parameters using <a href="#Type_unification">type unification</a>.
+       If unification fails, type inference fails.
+       </p>
 </li>
 <li>
-       The second phase considers the entries of list <i>Lu</i>. Type parameters for
-       which the type argument has already been determined are ignored in this phase.
-       For each remaining pair, the parameter type (which is a single type parameter) and
-       the <a href="#Constants">default type</a> of the corresponding untyped argument is
-       unified. If unification fails, type inference fails.
+       <p>
+       For each bound type parameter <code>P<sub>k</sub></code> for which no type argument
+       has been inferred yet and for which one or more pairs
+       <code>(c<sub>j</sub>, P<sub>k</sub>)</code> with that same type parameter
+       were collected, determine the <a href="#Constant_expressions">constant kind</a>
+       of the constants <code>c<sub>j</sub></code> in all those pairs the same way as for
+       <a href="#Constant_expressions">constant expressions</a>.
+       The type argument for <code>P<sub>k</sub></code> is the
+       <a href="#Constants">default type</a> for the determined constant kind.
+       If a constant kind cannot be determined due to conflicting constant kinds,
+       type inference fails.
+       </p>
 </li>
 </ol>
 
 <p>
-While unification is successful, processing of each list continues until all list elements
-are considered, even if all type arguments are inferred before the last list element has
-been processed.
+If not all type arguments have been found after these two phases, type inference fails.
 </p>
 
 <p>
-Example:
+If the two phases are successful, type inference determined a type argument for each
+bound type parameter:
 </p>
 
 <pre>
-func min[T ~int|~float64](x, y T) T
-
-var x int
-min(x, 2.0)    // T is int, inferred from typed argument x; 2.0 is assignable to int
-min(1.0, 2.0)  // T is float64, inferred from default type for 1.0 and matches default type for 2.0
-min(1.0, 2)    // illegal: default type float64 (for 1.0) doesn't match default type int (for 2)
+       P<sub>k</sub> ➞ A<sub>k</sub>
 </pre>
 
 <p>
-In the example <code>min(1.0, 2)</code>, processing the function argument <code>1.0</code>
-yields the substitution map entry <code>T</code> &RightArrow; <code>float64</code>. Because
-processing continues until all untyped arguments are considered, an error is reported. This
-ensures that type inference does not depend on the order of the untyped arguments.
+A type argument <code>A<sub>k</sub></code> may be a composite type,
+containing other bound type parameters <code>P<sub>k</sub></code> as element types
+(or even be just another bound type parameter).
+In a process of repeated simplification, the bound type parameters in each type
+argument are substituted with the respective type arguments for those type
+parameters until each type argument is free of bound type parameters.
+</p>
+
+<p>
+If type arguments contain cyclic references to themselves
+through bound type parameters, simplification and thus type
+inference fails.
+Otherwise, type inference succeeds.
 </p>
 
-<h4 id="Constraint_type_inference">Constraint type inference</h4>
+<h4 id="Type_unification">Type unification</h4>
 
 <p>
-Constraint type inference infers type arguments by considering type constraints.
-If a type parameter <code>P</code> has a constraint with a
-<a href="#Core_types">core type</a> <code>C</code>,
-<a href="#Type_unification">unifying</a> <code>P</code> with <code>C</code>
-may infer additional type arguments, either the type argument for <code>P</code>,
-or if that is already known, possibly the type arguments for type parameters
-used in <code>C</code>.
+Type inference solves type equations through <i>type unification</i>.
+Type unification recursively compares the LHS and RHS types of an
+equation, where either or both types may be or contain bound type parameters,
+and looks for type arguments for those type parameters such that the LHS
+and RHS match (become identical or assignment-compatible, depending on
+context).
+To that effect, type inference maintains a map of bound type parameters
+to inferred type arguments; this map is consulted and updated during type unification.
+Initially, the bound type parameters are known but the map is empty.
+During type unification, if a new type argument <code>A</code> is inferred,
+the respective mapping <code>P ➞ A</code> from type parameter to argument
+is added to the map.
+Conversely, when comparing types, a known type argument
+(a type argument for which a map entry already exists)
+takes the place of its corresponding type parameter.
+As type inference progresses, the map is populated more and more
+until all equations have been considered, or until unification fails.
+Type inference succeeds if no unification step fails and the map has
+an entry for each type parameter.
 </p>
 
 <p>
-For instance, consider the type parameter list with type parameters <code>List</code> and
-<code>Elem</code>:
+For example, given the type equation with the bound type parameter
+<code>P</code>
 </p>
 
 <pre>
-[List ~[]Elem, Elem any]
+       [10]struct{ elem P, list []P } ≡<sub>A</sub> [10]struct{ elem string; list []string }
 </pre>
 
 <p>
-Constraint type inference can deduce the type of <code>Elem</code> from the type argument
-for <code>List</code> because <code>Elem</code> is a type parameter in the core type
-<code>[]Elem</code> of <code>List</code>.
-If the type argument is <code>Bytes</code>:
+type inference starts with an empty map.
+Unification first compares the top-level structure of the LHS and RHS
+types.
+Both are arrays of the same length; they unify if the element types unify.
+Both element types are structs; they unify if they have
+the same number of fields with the same names and if the
+field types unify.
+The type argument for <code>P</code> is not known yet (there is no map entry),
+so unifying <code>P</code> with <code>string</code> adds
+the mapping <code>P ➞ string</code> to the map.
+Unifying the types of the <code>list</code> field requires
+unifying <code>[]P</code> and <code>[]string</code> and
+thus <code>P</code> and <code>string</code>.
+Since the type argument for <code>P</code> is known at this point
+(there is a map entry for <code>P</code>), its type argument
+<code>string</code> takes the place of <code>P</code>.
+And since <code>string</code> is identical to <code>string</code>,
+this unification step succeeds as well.
+Unification of the LHS and RHS of the equation is now finished.
+Type inference succeeds because there is only one type equation,
+no unification step failed, and the map is fully populated.
 </p>
 
-<pre>
-type Bytes []byte
-</pre>
-
 <p>
-unifying the underlying type of <code>Bytes</code> with the core type means
-unifying <code>[]byte</code> with <code>[]Elem</code>. That unification succeeds and yields
-the <a href="#Type_unification">substitution map</a> entry
-<code>Elem</code> &RightArrow; <code>byte</code>.
-Thus, in this example, constraint type inference can infer the second type argument from the
-first one.
+Unification uses a combination of <i>exact</i> and <i>loose</i>
+unification depending on whether two types have to be
+<a href="#Type_identity">identical</a>,
+<a href="#Assignability">assignment-compatible</a>, or
+only structurally equal.
+The respective <a href="#Type_unification_rules">type unification rules</a>
+are spelled out in detail in the <a href="#Appendix">Appendix</a>.
 </p>
 
 <p>
-Using the core type of a constraint may lose some information: In the (unlikely) case that
-the constraint's type set contains a single <a href="#Type_definitions">defined type</a>
-<code>N</code>, the corresponding core type is <code>N</code>'s underlying type rather than
-<code>N</code> itself. In this case, constraint type inference may succeed but instantiation
-will fail because the inferred type is not in the type set of the constraint.
-Thus, constraint type inference uses the <i>adjusted core type</i> of
-a constraint: if the type set contains a single type, use that type; otherwise use the
-constraint's core type.
+For an equation of the form <code>X ≡<sub>A</sub> Y</code>,
+where <code>X</code> and <code>Y</code> are types involved
+in an assignment (including parameter passing and return statements),
+the top-level type structures may unify loosely but element types
+must unify exactly, matching the rules for assignments.
 </p>
 
 <p>
-Generally, constraint type inference proceeds in two phases: Starting with a given
-substitution map <i>M</i>
+For an equation of the form <code>P ≡<sub>C</sub> C</code>,
+where <code>P</code> is a type parameter and <code>C</code>
+its corresponding constraint, the unification rules are bit
+more complicated:
 </p>
 
-<ol>
+<ul>
 <li>
-For all type parameters with an adjusted core type, unify the type parameter with that
-type. If any unification fails, constraint type inference fails.
+       If <code>C</code> has a <a href="#Core_types">core type</a>
+       <code>core(C)</code>
+       and <code>P</code> has a known type argument <code>A</code>,
+       <code>core(C)</code> and <code>A</code> must unify loosely.
+       If <code>P</code> does not have a known type argument
+       and <code>C</code> contains exactly one type term <code>T</code>
+       that is not an underlying (tilde) type, unification adds the
+       mapping <code>P ➞ T</code> to the map.
 </li>
-
 <li>
-At this point, some entries in <i>M</i> may map type parameters to other
-type parameters or to types containing type parameters. For each entry
-<code>P</code> &RightArrow; <code>A</code> in <i>M</i> where <code>A</code> is or
-contains type parameters <code>Q</code> for which there exist entries
-<code>Q</code> &RightArrow; <code>B</code> in <i>M</i>, substitute those
-<code>Q</code> with the respective <code>B</code> in <code>A</code>.
-Stop when no further substitution is possible.
+       If <code>C</code> does not have a core type
+       and <code>P</code> has a known type argument <code>A</code>,
+       <code>A</code> must have all methods of <code>C</code>, if any,
+       and corresponding method types must unify exactly.
 </li>
-</ol>
-
-<p>
-The result of constraint type inference is the final substitution map <i>M</i> from type
-parameters <code>P</code> to type arguments <code>A</code> where no type parameter <code>P</code>
-appears in any of the <code>A</code>.
-</p>
-
-<p>
-For instance, given the type parameter list
-</p>
-
-<pre>
-[A any, B []C, C *A]
-</pre>
-
-<p>
-and the single provided type argument <code>int</code> for type parameter <code>A</code>,
-the initial substitution map <i>M</i> contains the entry <code>A</code> &RightArrow; <code>int</code>.
-</p>
-
-<p>
-In the first phase, the type parameters <code>B</code> and <code>C</code> are unified
-with the core type of their respective constraints. This adds the entries
-<code>B</code> &RightArrow; <code>[]C</code> and <code>C</code> &RightArrow; <code>*A</code>
-to <i>M</i>.
-
-<p>
-At this point there are two entries in <i>M</i> where the right-hand side
-is or contains type parameters for which there exists other entries in <i>M</i>:
-<code>[]C</code> and <code>*A</code>.
-In the second phase, these type parameters are replaced with their respective
-types. It doesn't matter in which order this happens. Starting with the state
-of <i>M</i> after the first phase:
-</p>
-
-<p>
-<code>A</code> &RightArrow; <code>int</code>,
-<code>B</code> &RightArrow; <code>[]C</code>,
-<code>C</code> &RightArrow; <code>*A</code>
-</p>
-
-<p>
-Replace <code>A</code> on the right-hand side of &RightArrow; with <code>int</code>:
-</p>
-
-<p>
-<code>A</code> &RightArrow; <code>int</code>,
-<code>B</code> &RightArrow; <code>[]C</code>,
-<code>C</code> &RightArrow; <code>*int</code>
-</p>
-
-<p>
-Replace <code>C</code> on the right-hand side of &RightArrow; with <code>*int</code>:
-</p>
-
-<p>
-<code>A</code> &RightArrow; <code>int</code>,
-<code>B</code> &RightArrow; <code>[]*int</code>,
-<code>C</code> &RightArrow; <code>*int</code>
-</p>
+</ul>
 
 <p>
-At this point no further substitution is possible and the map is full.
-Therefore, <code>M</code> represents the final map of type parameters
-to type arguments for the given type parameter list.
+When solving type equations from type constraints,
+solving one equation may infer additional type arguments,
+which in turn may enable solving other equations that depend
+on those type arguments.
+Type inference repeats type unification as long as new type
+arguments are inferred.
 </p>
 
 <h3 id="Operators">Operators</h3>
@@ -4860,6 +4803,7 @@ As the  <code>++</code> and <code>--</code> operators form
 statements, not expressions, they fall
 outside the operator hierarchy.
 As a consequence, statement <code>*p++</code> is the same as <code>(*p)++</code>.
+</p>
 <p>
 There are five precedence levels for binary operators.
 Multiplication operators bind strongest, followed by addition
@@ -4882,12 +4826,13 @@ For instance, <code>x / y * z</code> is the same as <code>(x / y) * z</code>.
 </p>
 
 <pre>
-+x
-23 + 3*x[i]
-x &lt;= f()
-^a &gt;&gt; b
-f() || g()
-x == y+1 &amp;&amp; &lt;-chanInt &gt; 0
++x                         // x
+42 + a - b                 // (42 + a) - b
+23 + 3*x[i]                // 23 + (3 * x[i])
+x &lt;= f()                   // x &lt;= f()
+^a &gt;&gt; b                    // (^a) >> b
+f() || g()                 // f() || g()
+x == y+1 &amp;&amp; &lt;-chanInt &gt; 0  // (x == (y+1)) && ((<-chanInt) > 0)
 </pre>
 
 
@@ -5264,7 +5209,7 @@ Specifically:
 <p>
 Logical operators apply to <a href="#Boolean_types">boolean</a> values
 and yield a result of the same type as the operands.
-The right operand is evaluated conditionally.
+The left operand is evaluated, and then the right if the condition requires it.
 </p>
 
 <pre class="grammar">
@@ -5457,7 +5402,7 @@ in any of these cases:
        ignoring struct tags (see below),
        <code>x</code>'s type and <code>T</code> are not
        <a href="#Type_parameter_declarations">type parameters</a> but have
-       <a href="#Type_identity">identical</a> <a href="#Types">underlying types</a>.
+       <a href="#Type_identity">identical</a> <a href="#Underlying_types">underlying types</a>.
        </li>
        <li>
        ignoring struct tags (see below),
@@ -5587,21 +5532,6 @@ succeeds but the result value is implementation-dependent.
 <h4 id="Conversions_to_and_from_a_string_type">Conversions to and from a string type</h4>
 
 <ol>
-<li>
-Converting a signed or unsigned integer value to a string type yields a
-string containing the UTF-8 representation of the integer. Values outside
-the range of valid Unicode code points are converted to <code>"\uFFFD"</code>.
-
-<pre>
-string('a')       // "a"
-string(-1)        // "\ufffd" == "\xef\xbf\xbd"
-string(0xf8)      // "\u00f8" == "ø" == "\xc3\xb8"
-
-type myString string
-myString(0x65e5)  // "\u65e5" == "日" == "\xe6\x97\xa5"
-</pre>
-</li>
-
 <li>
 Converting a slice of bytes to a string type yields
 a string whose successive bytes are the elements of the slice.
@@ -5641,7 +5571,7 @@ myString([]myRune{0x1f30e})              // "\U0001f30e" == "🌎"
 
 <li>
 Converting a value of a string type to a slice of bytes type
-yields a slice whose successive elements are the bytes of the string.
+yields a non-nil slice whose successive elements are the bytes of the string.
 
 <pre>
 []byte("hellø")             // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
@@ -5668,6 +5598,31 @@ runes("白鵬翔")              // []rune{0x767d, 0x9d6c, 0x7fd4}
 []myRune(myString("🌐"))    // []myRune{0x1f310}
 </pre>
 </li>
+
+<li>
+Finally, for historical reasons, an integer value may be converted to a string type.
+This form of conversion yields a string containing the (possibly multi-byte) UTF-8
+representation of the Unicode code point with the given integer value.
+Values outside the range of valid Unicode code points are converted to <code>"\uFFFD"</code>.
+
+<pre>
+string('a')          // "a"
+string(65)           // "A"
+string('\xf8')       // "\u00f8" == "ø" == "\xc3\xb8"
+string(-1)           // "\ufffd" == "\xef\xbf\xbd"
+
+type myString string
+myString('\u65e5')   // "\u65e5" == "日" == "\xe6\x97\xa5"
+</pre>
+
+Note: This form of conversion may eventually be removed from the language.
+The <a href="/pkg/cmd/vet"><code>go vet</code></a> tool flags certain
+integer-to-string conversions as potential errors.
+Library functions such as
+<a href="/pkg/unicode/utf8#AppendRune"><code>utf8.AppendRune</code></a> or
+<a href="/pkg/unicode/utf8#EncodeRune"><code>utf8.EncodeRune</code></a>
+should be used instead.
+</li>
 </ol>
 
 <h4 id="Conversions_from_slice_to_array_or_array_pointer">Conversions from slice to array or array pointer</h4>
@@ -5832,24 +5787,28 @@ determine the evaluation order of individual initialization expressions in
 Otherwise, when evaluating the <a href="#Operands">operands</a> of an
 expression, assignment, or
 <a href="#Return_statements">return statement</a>,
-all function calls, method calls, and
-communication operations are evaluated in lexical left-to-right
-order.
+all function calls, method calls,
+<a href="#Receive operator">receive operations</a>,
+and <a href="#Logical_operators">binary logical operations</a>
+are evaluated in lexical left-to-right order.
 </p>
 
 <p>
 For example, in the (function-local) assignment
 </p>
 <pre>
-y[f()], ok = g(h(), i()+x[j()], &lt;-c), k()
+y[f()], ok = g(z || h(), i()+x[j()], &lt;-c), k()
 </pre>
 <p>
 the function calls and communication happen in the order
-<code>f()</code>, <code>h()</code>, <code>i()</code>, <code>j()</code>,
+<code>f()</code>, <code>h()</code> (if <code>z</code>
+evaluates to false), <code>i()</code>, <code>j()</code>,
 <code>&lt;-c</code>, <code>g()</code>, and <code>k()</code>.
 However, the order of those events compared to the evaluation
 and indexing of <code>x</code> and the evaluation
-of <code>y</code> is not specified.
+of <code>y</code> and <code>z</code> is not specified,
+except as required lexically. For instance, <code>g</code>
+cannot be called before its arguments are evaluated.
 </p>
 
 <pre>
@@ -6593,8 +6552,9 @@ for      { S() }    is the same as    for true     { S() }
 
 <p>
 A "for" statement with a "range" clause
-iterates through all entries of an array, slice, string or map,
-or values received on a channel. For each entry it assigns <i>iteration values</i>
+iterates through all entries of an array, slice, string or map, values received on
+a channel, or integer values from zero to an upper limit.
+For each entry it assigns <i>iteration values</i>
 to corresponding <i>iteration variables</i> if present and then executes the block.
 </p>
 
@@ -6605,12 +6565,12 @@ RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
 <p>
 The expression on the right in the "range" clause is called the <i>range expression</i>,
 its <a href="#Core_types">core type</a> must be
-an array, pointer to an array, slice, string, map, or channel permitting
-<a href="#Receive_operator">receive operations</a>.
+an array, pointer to an array, slice, string, map, channel permitting
+<a href="#Receive_operator">receive operations</a>, or an integer.
 As with an assignment, if present the operands on the left must be
 <a href="#Address_operators">addressable</a> or map index expressions; they
-denote the iteration variables. If the range expression is a channel, at most
-one iteration variable is permitted, otherwise there may be up to two.
+denote the iteration variables. If the range expression is a channel or integer,
+at most one iteration variable is permitted, otherwise there may be up to two.
 If the last iteration variable is the <a href="#Blank_identifier">blank identifier</a>,
 the range clause is equivalent to the same clause without that identifier.
 </p>
@@ -6635,6 +6595,7 @@ array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
 string          s  string type            index    i  int    see below  rune
 map             m  map[K]V                key      k  K      m[k]       V
 channel         c  chan E, &lt;-chan E       element  e  E
+integer         n  integer type I         value    i  I
 </pre>
 
 <ol>
@@ -6673,6 +6634,12 @@ For channels, the iteration values produced are the successive values sent on
 the channel until the channel is <a href="#Close">closed</a>. If the channel
 is <code>nil</code>, the range expression blocks forever.
 </li>
+
+<li>
+For an integer value <code>n</code>, the iteration values 0 through <code>n-1</code>
+are produced in increasing order, with the same type as <code>n</code>.
+If <code>n</code> &lt= 0, the loop does not run any iterations.
+</li>
 </ol>
 
 <p>
@@ -6725,6 +6692,12 @@ for w := range ch {
 
 // empty a channel
 for range ch {}
+
+// call f(0), f(1), ... f(9)
+for i := range 10 {
+       // type of i is int (default type for untyped constant 10)
+       f(i)
+}
 </pre>
 
 
@@ -7292,7 +7265,8 @@ clear(t)    type parameter    see below
 </pre>
 
 <p>
-If the argument type is a <a href="#Type_parameter_declarations">type parameter</a>,
+If the type of the argument to <code>clear</code> is a
+<a href="#Type_parameter_declarations">type parameter</a>,
 all types in its type set must be maps or slices, and <code>clear</code>
 performs the operation corresponding to the actual type argument.
 </p>
@@ -8258,7 +8232,7 @@ of if the general conversion rules take care of this.
 <p>
 A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
 value may not be <a href="#Address_operators">dereferenced</a>.
-Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be
+Any pointer or value of <a href="#Underlying_types">underlying type</a> <code>uintptr</code> can be
 <a href="#Conversions">converted</a> to a type of underlying type <code>Pointer</code> and vice versa.
 The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
 </p>
@@ -8406,3 +8380,145 @@ The following minimal alignment properties are guaranteed:
 <p>
 A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.
 </p>
+
+<h2 id="Appendix">Appendix</h2>
+
+<h3 id="Type_unification_rules">Type unification rules</h3>
+
+<p>
+The type unification rules describe if and how two types unify.
+The precise details are relevant for Go implementations,
+affect the specifics of error messages (such as whether
+a compiler reports a type inference or other error),
+and may explain why type inference fails in unusual code situations.
+But by and large these rules can be ignored when writing Go code:
+type inference is designed to mostly "work as expected",
+and the unification rules are fine-tuned accordingly.
+</p>
+
+<p>
+Type unification is controlled by a <i>matching mode</i>, which may
+be <i>exact</i> or <i>loose</i>.
+As unification recursively descends a composite type structure,
+the matching mode used for elements of the type, the <i>element matching mode</i>,
+remains the same as the matching mode except when two types are unified for
+<a href="#Assignability">assignability</a> (<code>≡<sub>A</sub></code>):
+in this case, the matching mode is <i>loose</i> at the top level but
+then changes to <i>exact</i> for element types, reflecting the fact
+that types don't have to be identical to be assignable.
+</p>
+
+<p>
+Two types that are not bound type parameters unify exactly if any of
+following conditions is true:
+</p>
+
+<ul>
+<li>
+       Both types are <a href="#Type_identity">identical</a>.
+</li>
+<li>
+       Both types have identical structure and their element types
+       unify exactly.
+</li>
+<li>
+       Exactly one type is an <a href="#Type_inference">unbound</a>
+       type parameter with a <a href="#Core_types">core type</a>,
+       and that core type unifies with the other type per the
+       unification rules for <code>≡<sub>A</sub></code>
+       (loose unification at the top level and exact unification
+       for element types).
+</li>
+</ul>
+
+<p>
+If both types are bound type parameters, they unify per the given
+matching modes if:
+</p>
+
+<ul>
+<li>
+       Both type parameters are identical.
+</li>
+<li>
+       At most one of the type parameters has a known type argument.
+       In this case, the type parameters are <i>joined</i>:
+       they both stand for the same type argument.
+       If neither type parameter has a known type argument yet,
+       a future type argument inferred for one the type parameters
+       is simultaneously inferred for both of them.
+</li>
+<li>
+       Both type parameters have a known type argument
+       and the type arguments unify per the given matching modes.
+</li>
+</ul>
+
+<p>
+A single bound type parameter <code>P</code> and another type <code>T</code> unify
+per the given matching modes if:
+</p>
+
+<ul>
+<li>
+       <code>P</code> doesn't have a known type argument.
+       In this case, <code>T</code> is inferred as the type argument for <code>P</code>.
+</li>
+<li>
+       <code>P</code> does have a known type argument <code>A</code>,
+       <code>A</code> and <code>T</code> unify per the given matching modes,
+       and one of the following conditions is true:
+       <ul>
+       <li>
+               Both <code>A</code> and <code>T</code> are interface types:
+               In this case, if both <code>A</code> and <code>T</code> are
+               also <a href="#Type_definitions">defined</a> types,
+               they must be <a href="#Type_identity">identical</a>.
+               Otherwise, if neither of them is a defined type, they must
+               have the same number of methods
+               (unification of <code>A</code> and <code>T</code> already
+               established that the methods match).
+       </li>
+       <li>
+               Neither <code>A</code> nor <code>T</code> are interface types:
+               In this case, if <code>T</code> is a defined type, <code>T</code>
+               replaces <code>A</code> as the inferred type argument for <code>P</code>.
+       </li>
+       </ul>
+</li>
+</ul>
+
+<p>
+Finally, two types that are not bound type parameters unify loosely
+(and per the element matching mode) if:
+</p>
+
+<ul>
+<li>
+       Both types unify exactly.
+</li>
+<li>
+       One type is a <a href="#Type_definitions">defined type</a>,
+       the other type is a type literal, but not an interface,
+       and their underlying types unify per the element matching mode.
+</li>
+<li>
+       Both types are interfaces (but not type parameters) with
+       identical <a href="#Interface_types">type terms</a>,
+       both or neither embed the predeclared type
+       <a href="#Predeclared_identifiers">comparable</a>,
+       corresponding method types unify exactly,
+       and the method set of one of the interfaces is a subset of
+       the method set of the other interface.
+</li>
+<li>
+       Only one type is an interface (but not a type parameter),
+       corresponding methods of the two types unify per the element matching mode,
+       and the method set of the interface is a subset of
+       the method set of the other type.
+</li>
+<li>
+       Both types have the same structure and their element types
+       unify per the element matching mode.
+</li>
+</ul>