]> 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 3405b7d887ee25698747c7b8d9d66e8a36b93dce..18f88d5eadef99afc2e6f9ff9bb8784fb007dba3 100644 (file)
@@ -1,21 +1,16 @@
 <!--{
-       "Title": "The Go Programming Language Specification - Go 1.18 Draft (incomplete)",
-       "Subtitle": "Version of Feb 10, 2022",
+       "Title": "The Go Programming Language Specification",
+       "Subtitle": "Version of Nov 1, 2023",
        "Path": "/ref/spec"
 }-->
 
-<h2>Earlier version</h2>
-
-<p>
-For the pre-Go1.18 specification without generics support see
-<a href="/doc/go1.17_spec.html">The Go Programming Language Specification</a>.
-</p>
-
 <h2 id="Introduction">Introduction</h2>
 
 <p>
-This is a reference manual for the Go programming language. For
-more information and other documents, see <a href="/">golang.org</a>.
+This is the reference manual for the Go programming language.
+The pre-Go1.18 version, without generics, can be found
+<a href="/doc/go1.17_spec.html">here</a>.
+For more information and other documents, see <a href="/">golang.org</a>.
 </p>
 
 <p>
@@ -27,20 +22,23 @@ dependencies.
 </p>
 
 <p>
-The grammar is compact and simple to parse, allowing for easy analysis
+The syntax is compact and simple to parse, allowing for easy analysis
 by automatic tools such as integrated development environments.
 </p>
 
 <h2 id="Notation">Notation</h2>
 <p>
-The syntax is specified using Extended Backus-Naur Form (EBNF):
+The syntax is specified using a
+<a href="https://en.wikipedia.org/wiki/Wirth_syntax_notation">variant</a>
+of Extended Backus-Naur Form (EBNF):
 </p>
 
 <pre class="grammar">
+Syntax      = { Production } .
 Production  = production_name "=" [ Expression ] "." .
-Expression  = Alternative { "|" Alternative } .
-Alternative = Term { Term } .
-Term        = production_name | token [ "…" token ] | Group | Option | Repetition .
+Expression  = Term { "|" Term } .
+Term        = Factor { Factor } .
+Factor      = production_name | token [ "…" token ] | Group | Option | Repetition .
 Group       = "(" Expression ")" .
 Option      = "[" Expression "]" .
 Repetition  = "{" Expression "}" .
@@ -58,7 +56,7 @@ operators, in increasing precedence:
 </pre>
 
 <p>
-Lower-case production names are used to identify lexical tokens.
+Lowercase production names are used to identify lexical (terminal) tokens.
 Non-terminals are in CamelCase. Lexical tokens are enclosed in
 double quotes <code>""</code> or back quotes <code>``</code>.
 </p>
@@ -84,7 +82,7 @@ will use the unqualified term <i>character</i> to refer to a Unicode code point
 in the source text.
 </p>
 <p>
-Each code point is distinct; for instance, upper and lower case letters
+Each code point is distinct; for instance, uppercase and lowercase letters
 are different characters.
 </p>
 <p>
@@ -101,13 +99,13 @@ A byte order mark may be disallowed anywhere else in the source.
 <h3 id="Characters">Characters</h3>
 
 <p>
-The following terms are used to denote specific Unicode character classes:
+The following terms are used to denote specific Unicode character categories:
 </p>
 <pre class="ebnf">
 newline        = /* the Unicode code point U+000A */ .
 unicode_char   = /* an arbitrary Unicode code point except newline */ .
-unicode_letter = /* a Unicode code point classified as "Letter" */ .
-unicode_digit  = /* a Unicode code point classified as "Number, decimal digit" */ .
+unicode_letter = /* a Unicode code point categorized as "Letter" */ .
+unicode_digit  = /* a Unicode code point categorized as "Number, decimal digit" */ .
 </pre>
 
 <p>
@@ -120,7 +118,7 @@ as Unicode letters, and those in the Number category Nd as Unicode digits.
 <h3 id="Letters_and_digits">Letters and digits</h3>
 
 <p>
-The underscore character <code>_</code> (U+005F) is considered a letter.
+The underscore character <code>_</code> (U+005F) is considered a lowercase letter.
 </p>
 <pre class="ebnf">
 letter        = unicode_letter | "_" .
@@ -175,7 +173,7 @@ valid token.
 <h3 id="Semicolons">Semicolons</h3>
 
 <p>
-The formal grammar uses semicolons <code>";"</code> as terminators in
+The formal syntax uses semicolons <code>";"</code> as terminators in
 a number of productions. Go programs may omit most of these semicolons
 using the following two rules:
 </p>
@@ -265,7 +263,7 @@ continue     for          import       return       var
 
 <p>
 The following character sequences represent <a href="#Operators">operators</a>
-(including <a href="#Assignments">assignment operators</a>) and punctuation:
+(including <a href="#Assignment_statements">assignment operators</a>) and punctuation:
 </p>
 <pre class="grammar">
 +    &amp;     +=    &amp;=     &amp;&amp;    ==    !=    (    )
@@ -411,7 +409,7 @@ An imaginary literal represents the imaginary part of a
 <a href="#Constants">complex constant</a>.
 It consists of an <a href="#Integer_literals">integer</a> or
 <a href="#Floating-point_literals">floating-point</a> literal
-followed by the lower-case letter <code>i</code>.
+followed by the lowercase letter <code>i</code>.
 The value of an imaginary literal is the value of the respective
 integer or floating-point literal multiplied by the imaginary unit <i>i</i>.
 </p>
@@ -504,8 +502,9 @@ After a backslash, certain single-character escapes represent special values:
 </pre>
 
 <p>
-All other sequences starting with a backslash are illegal inside rune literals.
+An unrecognized character following a backslash in a rune literal is illegal.
 </p>
+
 <pre class="ebnf">
 rune_lit         = "'" ( unicode_value | byte_value ) "'" .
 unicode_value    = unicode_char | little_u_value | big_u_value | escaped_char .
@@ -532,8 +531,10 @@ escaped_char     = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `
 '\U00101234'
 '\''         // rune literal containing single quote character
 'aa'         // illegal: too many characters
+'\k'         // illegal: k is not recognized after a backslash
 '\xa'        // illegal: too few hexadecimal digits
 '\0'         // illegal: too few octal digits
+'\400'       // illegal: octal value over 255
 '\uDFFF'     // illegal: surrogate half
 '\U00110000' // illegal: invalid Unicode code point
 </pre>
@@ -642,6 +643,7 @@ an identifier denoting a constant,
 a <a href="#Constant_expressions">constant expression</a>,
 a <a href="#Conversions">conversion</a> with a result that is a constant, or
 the result value of some built-in functions such as
+<code>min</code> or <code>max</code> applied to constant arguments,
 <code>unsafe.Sizeof</code> applied to <a href="#Package_unsafe">certain values</a>,
 <code>cap</code> or <code>len</code> applied to
 <a href="#Length_and_capacity">some expressions</a>,
@@ -675,7 +677,7 @@ containing only untyped constant operands are untyped.
 A constant may be given a type explicitly by a <a href="#Constant_declarations">constant declaration</a>
 or <a href="#Conversions">conversion</a>, or implicitly when used in a
 <a href="#Variable_declarations">variable declaration</a> or an
-<a href="#Assignments">assignment</a> or as an
+<a href="#Assignment_statements">assignment statement</a> or as an
 operand in an <a href="#Expressions">expression</a>.
 It is an error if the constant value
 cannot be <a href="#Representability">represented</a> as a value of the respective type.
@@ -689,7 +691,7 @@ constant is implicitly converted in contexts where a typed value is required,
 for instance, in a <a href="#Short_variable_declarations">short variable declaration</a>
 such as <code>i := 0</code> where there is no explicit type.
 The default type of an untyped constant is <code>bool</code>, <code>rune</code>,
-<code>int</code>, <code>float64</code>, <code>complex128</code> or <code>string</code>
+<code>int</code>, <code>float64</code>, <code>complex128</code>, or <code>string</code>
 respectively, depending on whether it is a boolean, rune, integer, floating-point,
 complex, or string constant.
 </p>
@@ -761,7 +763,7 @@ type given in its declaration, the type provided in the
 <code>new</code> call or composite literal, or the type of
 an element of a structured variable.
 Variables of interface type also have a distinct <i>dynamic type</i>,
-which is the concrete type of the value assigned to the variable at run time
+which is the (non-interface) type of the value assigned to the variable at run time
 (unless the value is the predeclared identifier <code>nil</code>,
 which has no type).
 The dynamic type may vary during execution but values stored in interface
@@ -779,7 +781,7 @@ x = v              // x has value (*T)(nil) and dynamic type *T
 <p>
 A variable's value is retrieved by referring to the variable in an
 <a href="#Expressions">expression</a>; it is the most recent value
-<a href="#Assignments">assigned</a> to the variable.
+<a href="#Assignment_statements">assigned</a> to the variable.
 If a variable has not yet been assigned a value, its value is the
 <a href="#The_zero_value">zero value</a> for its type.
 </p>
@@ -801,13 +803,13 @@ TypeName  = identifier | QualifiedIdent .
 TypeArgs  = "[" TypeList [ "," ] "]" .
 TypeList  = Type { "," Type } .
 TypeLit   = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
-           SliceType | MapType | ChannelType .
+            SliceType | MapType | ChannelType .
 </pre>
 
 <p>
 The language <a href="#Predeclared_identifiers">predeclares</a> certain type names.
 Others are introduced with <a href="#Type_declarations">type declarations</a>
-or <a href="#Type_parameter_lists">type parameter lists</a>.
+or <a href="#Type_parameter_declarations">type parameter lists</a>.
 <i>Composite types</i>&mdash;array, struct, pointer, function,
 interface, slice, map, and channel types&mdash;may be constructed using
 type literals.
@@ -882,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>
 
@@ -943,6 +945,29 @@ multi-dimensional types.
 [2][2][2]float64  // same as [2]([2]([2]float64))
 </pre>
 
+<p>
+An array type <code>T</code> may not have an element of type <code>T</code>,
+or of a type containing <code>T</code> as a component, directly or indirectly,
+if those containing types are only array or struct types.
+</p>
+
+<pre>
+// invalid array types
+type (
+       T1 [10]T1                 // element type of T1 is T1
+       T2 [10]struct{ f T2 }     // T2 contains T2 as component of a struct
+       T3 [10]T4                 // T3 contains T3 as component of a struct in T4
+       T4 struct{ f T3 }         // T4 contains T4 as component of array T3 in a struct
+)
+
+// valid array types
+type (
+       T5 [10]*T5                // T5 contains T5 as component of a pointer
+       T6 [10]func() T6          // T6 contains T6 as component of a function type
+       T7 [10]struct{ f []T7 }   // T7 contains T7 as component of a slice in a struct
+)
+</pre>
+
 <h3 id="Slice_types">Slice types</h3>
 
 <p>
@@ -982,7 +1007,7 @@ built-in function <a href="#Length_and_capacity"><code>cap(a)</code></a>.
 </p>
 
 <p>
-A new, initialized slice value for a given element type <code>T</code> is
+A new, initialized slice value for a given element type <code>T</code> may be
 made using the built-in function
 <a href="#Making_slices_maps_and_channels"><code>make</code></a>,
 which takes a slice type
@@ -1026,7 +1051,7 @@ be <a href="#Uniqueness_of_identifiers">unique</a>.
 <pre class="ebnf">
 StructType    = "struct" "{" { FieldDecl ";" } "}" .
 FieldDecl     = (IdentifierList Type | EmbeddedField) [ Tag ] .
-EmbeddedField = [ "*" ] TypeName .
+EmbeddedField = [ "*" ] TypeName [ TypeArgs ] .
 Tag           = string_lit .
 </pre>
 
@@ -1090,7 +1115,7 @@ of a struct except that they cannot be used as field names in
 </p>
 
 <p>
-Given a struct type <code>S</code> and a <a href="#Type_definitions">defined type</a>
+Given a struct type <code>S</code> and a <a href="#Types">named type</a>
 <code>T</code>, promoted methods are included in the method set of the struct as follows:
 </p>
 <ul>
@@ -1135,6 +1160,29 @@ struct {
 }
 </pre>
 
+<p>
+A struct type <code>T</code> may not contain a field of type <code>T</code>,
+or of a type containing <code>T</code> as a component, directly or indirectly,
+if those containing types are only array or struct types.
+</p>
+
+<pre>
+// invalid struct types
+type (
+       T1 struct{ T1 }            // T1 contains a field of T1
+       T2 struct{ f [10]T2 }      // T2 contains T2 as component of an array
+       T3 struct{ T4 }            // T3 contains T3 as component of an array in struct T4
+       T4 struct{ f [10]T3 }      // T4 contains T4 as component of struct T3 in an array
+)
+
+// valid struct types
+type (
+       T5 struct{ f *T5 }         // T5 contains T5 as component of a pointer
+       T6 struct{ f func() T6 }   // T6 contains T6 as component of a function type
+       T7 struct{ f [10][]T7 }    // T7 contains T7 as component of a slice in an array
+)
+</pre>
+
 <h3 id="Pointer_types">Pointer types</h3>
 
 <p>
@@ -1205,7 +1253,8 @@ func(n int) func(p *T)
 <p>
 An interface type defines a <i>type set</i>.
 A variable of interface type can store a value of any type that is in the type
-set of the interface. Such a type is said to <i>implement the interface</i>.
+set of the interface. Such a type is said to
+<a href="#Implementing_an_interface">implement the interface</a>.
 The value of an uninitialized variable of interface type is <code>nil</code>.
 </p>
 
@@ -1281,7 +1330,8 @@ then the <code>File</code> interface is implemented by both <code>S1</code> and
 <p>
 Every type that is a member of the type set of an interface implements that interface.
 Any given type may implement several distinct interfaces.
-For instance, all types implement the <i>empty interface</i> which stands for the set of all types:
+For instance, all types implement the <i>empty interface</i> which stands for the set
+of all (non-interface) types:
 </p>
 
 <pre>
@@ -1365,7 +1415,7 @@ type ReadCloser interface {
 }
 </pre>
 
-<h4 id="Generenal_interfaces">General interfaces</h4>
+<h4 id="General_interfaces">General interfaces</h4>
 
 <p>
 In their most general form, an interface element may also be an arbitrary type term
@@ -1376,14 +1426,14 @@ definition of an interface's type set as follows:
 </p>
 
 <ul>
-       <li>The type set of the empty interface is the set of all types.
+       <li>The type set of the empty interface is the set of all non-interface types.
        </li>
 
        <li>The type set of a non-empty interface is the intersection of the type sets
                of its interface elements.
        </li>
 
-       <li>The type set of a method specification is the set of types
+       <li>The type set of a method specification is the set of all non-interface types
                whose method sets include that method.
        </li>
 
@@ -1392,7 +1442,7 @@ definition of an interface's type set as follows:
        </li>
 
        <li>The type set of a term of the form <code>~T</code>
-               is the set of types whose underlying type is <code>T</code>.
+               is the set of all types whose underlying type is <code>T</code>.
        </li>
 
        <li>The type set of a <i>union</i> of terms
@@ -1401,6 +1451,19 @@ definition of an interface's type set as follows:
        </li>
 </ul>
 
+<p>
+The quantification "the set of all non-interface types" refers not just to all (non-interface)
+types declared in the program at hand, but all possible types in all possible programs, and
+hence is infinite.
+Similarly, given the set of all non-interface types that implement a particular method, the
+intersection of the method sets of those types will contain exactly that method, even if all
+types in the program at hand always pair that method with another method.
+</p>
+
+<p>
+By construction, an interface's type set never contains an interface type.
+</p>
+
 <pre>
 // An interface representing only the type int.
 interface {
@@ -1412,7 +1475,7 @@ interface {
        ~int
 }
 
-// An interface representing all types with underlying type int which implement the String method.
+// An interface representing all types with underlying type int that implement the String method.
 interface {
        ~int
        String() string
@@ -1445,32 +1508,33 @@ Union elements denote unions of type sets:
 </p>
 
 <pre>
-// The Floats interface represents all floating-point types
+// The Float interface represents all floating-point types
 // (including any named types whose underlying types are
 // either float32 or float64).
-type Floats interface {
+type Float interface {
        ~float32 | ~float64
 }
 </pre>
 
 <p>
-In a union, a term cannot be a type parameter, and the type sets of all
+The type <code>T</code> in a term of the form <code>T</code> or <code>~T</code> cannot
+be a <a href="#Type_parameter_declarations">type parameter</a>, and the type sets of all
 non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).
 Given a type parameter <code>P</code>:
 </p>
 
 <pre>
 interface {
-       P                 // illegal: the term P is a type parameter
-       int | P           // illegal: the term P is a type parameter
-       ~int | MyInt      // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
-       float32 | Floats  // overlapping type sets but Floats is an interface
+       P                // illegal: P is a type parameter
+       int | ~P         // illegal: P is a type parameter
+       ~int | MyInt     // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
+       float32 | Float  // overlapping type sets but Float is an interface
 }
 </pre>
 
 <p>
 Implementation restriction:
-A union with more than one term cannot contain the
+A union (with more than one term) cannot contain the
 <a href="#Predeclared_identifiers">predeclared identifier</a> <code>comparable</code>
 or interfaces that specify methods, or embed <code>comparable</code> or interfaces
 that specify methods.
@@ -1484,41 +1548,66 @@ non-interface types.
 </p>
 
 <pre>
-var x Floats                     // illegal: Floats is not a basic interface
+var x Float                     // illegal: Float is not a basic interface
 
-var x interface{} = Floats(nil)  // illegal
+var x interface{} = Float(nil)  // illegal
 
 type Floatish struct {
-       f Floats                 // illegal
+       f Float                 // illegal
 }
 </pre>
 
-<!-- TODO The rule below needs to be generalized to interface elements.
-         It should be factored out and generalized to other types
-         such as arrays and structs which are currently missing such a
-         rule. See also #5069.
--->
-
 <p>
-An interface type <code>T</code> may not embed itself
-or any interface type that embeds <code>T</code>, recursively.
+An interface type <code>T</code> may not embed a type element
+that is, contains, or embeds <code>T</code>, directly or indirectly.
 </p>
 
 <pre>
-// illegal: Bad cannot embed itself
+// illegal: Bad may not embed itself
 type Bad interface {
        Bad
 }
 
-// illegal: Bad1 cannot embed itself using Bad2
+// illegal: Bad1 may not embed itself using Bad2
 type Bad1 interface {
        Bad2
 }
 type Bad2 interface {
        Bad1
 }
+
+// illegal: Bad3 may not embed a union containing Bad3
+type Bad3 interface {
+       ~int | ~string | Bad3
+}
+
+// illegal: Bad4 may not embed an array containing Bad4 as element type
+type Bad4 interface {
+       [10]Bad4
+}
 </pre>
 
+<h4 id="Implementing_an_interface">Implementing an interface</h4>
+
+<p>
+A type <code>T</code> implements an interface <code>I</code> if
+</p>
+
+<ul>
+<li>
+       <code>T</code> is not an interface and is an element of the type set of <code>I</code>; or
+</li>
+<li>
+       <code>T</code> is an interface and the type set of <code>T</code> is a subset of the
+       type set of <code>I</code>.
+</li>
+</ul>
+
+<p>
+A value of type <code>T</code> implements an interface if <code>T</code>
+implements the interface.
+</p>
+
 <h3 id="Map_types">Map types</h3>
 
 <p>
@@ -1554,10 +1643,12 @@ The number of map elements is called its length.
 For a map <code>m</code>, it can be discovered using the
 built-in function <a href="#Length_and_capacity"><code>len</code></a>
 and may change during execution. Elements may be added during execution
-using <a href="#Assignments">assignments</a> and retrieved with
+using <a href="#Assignment_statements">assignments</a> and retrieved with
 <a href="#Index_expressions">index expressions</a>; they may be removed with the
-<a href="#Deletion_of_map_elements"><code>delete</code></a> built-in function.
+<a href="#Deletion_of_map_elements"><code>delete</code></a> and
+<a href="#Clear"><code>clear</code></a> built-in function.
 </p>
+
 <p>
 A new, empty map value is made using the built-in
 function <a href="#Making_slices_maps_and_channels"><code>make</code></a>,
@@ -1597,7 +1688,7 @@ The optional <code>&lt;-</code> operator specifies the channel <i>direction</i>,
 <i>send</i> or <i>receive</i>. If a direction is given, the channel is <i>directional</i>,
 otherwise it is <i>bidirectional</i>.
 A channel may be constrained only to send or only to receive by
-<a href="#Assignments">assignment</a> or
+<a href="#Assignment_statements">assignment</a> or
 explicit <a href="#Conversions">conversion</a>.
 </p>
 
@@ -1662,25 +1753,6 @@ and a second goroutine receives them, the values are
 received in the order sent.
 </p>
 
-<h3 id="Type_parameters">Type parameters</h3>
-
-<p>
-A <i>type parameter</i> is an (unqualified) type name declared in the
-<a href="#Type_parameter_lists">type parameter list</a> of a
-<a href="#Function_declarations">function declaration</a> or
-<a href="#Type_definitions">type definition</a>; or in the receiver specification
-of a <a href="#Method_declarations">method declaration</a> that is associated
-with a generic type.
-A type parameter acts as a place holder for an (as of yet) unknown type in the declaration;
-the type parameter is replaced with a <i>type argument</i> upon
-<a href="#Instantiations">instantiation</a> of the generic function or type.
-</p>
-
-<p>
-The properties of a type parameter are determined by its
-<a href="#Type_constraints">type constraint</a>.
-</p>
-
 <h2 id="Properties_of_types_and_values">Properties of types and values</h2>
 
 <h3 id="Underlying_types">Underlying types</h3>
@@ -1690,10 +1762,9 @@ Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
 is one of the predeclared boolean, numeric, or string types, or a type literal,
 the corresponding underlying type is <code>T</code> itself.
 Otherwise, <code>T</code>'s underlying type is the underlying type of the
-type to which <code>T</code> refers in its <a href="#Type_declarations">type
-declaration</a>. The underlying type of a type parameter is the
-underlying type of its <a href="#Type_constraints">type constraint</a>, which
-is always an interface.
+type to which <code>T</code> refers in its declaration.
+For a type parameter that is the underlying type of its
+<a href="#Type_constraints">type constraint</a>, which is always an interface.
 </p>
 
 <pre>
@@ -1744,7 +1815,7 @@ direction.
 </ol>
 
 <p>
-All other interfaces don't have a core type.
+No other interfaces have a core type.
 </p>
 
 <p>
@@ -1764,7 +1835,7 @@ depending on the direction of the directional channels present.
 
 <p>
 By definition, a core type is never a <a href="#Type_definitions">defined type</a>,
-<a href="#Type_parameters">type parameter</a>, or
+<a href="#Type_parameter_declarations">type parameter</a>, or
 <a href="#Interface_types">interface type</a>.
 </p>
 
@@ -1784,7 +1855,7 @@ interface{ ~[]*data; String() string }    // []*data
 </pre>
 
 <p>
-Examples of interfaces whithout core types:
+Examples of interfaces without core types:
 </p>
 
 <pre>
@@ -1794,66 +1865,31 @@ interface{ chan int | chan&lt;- string }     // channels have different element
 interface{ &lt;-chan int | chan&lt;- int }      // directional channels have different directions
 </pre>
 
-<h3 id="Specific_types">Specific types</h3>
-
-<p>
-An interface specification that contains <a href="#Interface_types">type elements</a>
-defines a (possibly empty) set of <i>specific types</i>.
-Loosely speaking, these are the types <code>T</code> that appear in the
-interface definition in terms of the form <code>T</code>, <code>~T</code>,
-or in unions of such terms.
-</p>
-
 <p>
-More precisely, for a given interface, the set of specific types corresponds to
-the set 𝑅 of representative types of the interface, if 𝑅 is non-empty and finite.
-Otherwise, if 𝑅 is empty or infinite, the interface has <i>no specific types</i>.
+Some operations (<a href="#Slice_expressions">slice expressions</a>,
+<a href="#Appending_and_copying_slices"><code>append</code> and <code>copy</code></a>)
+rely on a slightly more loose form of core types which accept byte slices and strings.
+Specifically, if there are exactly two types, <code>[]byte</code> and <code>string</code>,
+which are the underlying types of all types in the type set of interface <code>T</code>,
+the core type of <code>T</code> is called <code>bytestring</code>.
 </p>
 
 <p>
-For a given interface, type element or type term, the set 𝑅 of representative types is defined as follows:
+Examples of interfaces with <code>bytestring</code> core types:
 </p>
 
-<ul>
-       <li>For an interface with no type elements, 𝑅 is the (infinite) set of all types.
-       </li>
-
-       <li>For an interface with type elements,
-               𝑅 is the intersection of the representative types of its type elements.
-       </li>
-
-       <li>For a non-interface type term <code>T</code> or a term of the form <code>~T</code>,
-               𝑅 is the set consisting of the type <code>T</code>.
-       </li>
-
-       <li>For a <i>union</i> of terms
-               <code>t<sub>1</sub>|t<sub>2</sub>|…|t<sub>n</sub></code>,
-               𝑅 is the union of the representative types of the terms.
-       </li>
-</ul>
-
-<p>
-An interface may have specific types even if its <a href="#Interface_types">type set</a>
-is empty.
-</p>
+<pre>
+interface{ int }                          // int (same as ordinary core type)
+interface{ []byte | string }              // bytestring
+interface{ ~[]byte | myString }           // bytestring
+</pre>
 
 <p>
-Examples of interfaces with their specific types:
+Note that <code>bytestring</code> is not a real type; it cannot be used to declare
+variables or compose other types. It exists solely to describe the behavior of some
+operations that read from a sequence of bytes, which may be a byte slice or a string.
 </p>
 
-<pre>
-interface{}                    // no specific types
-interface{ int }               // int
-interface{ ~string }           // string
-interface{ int|~string }       // int, string
-interface{ Celsius|Kelvin }    // Celsius, Kelvin
-interface{ float64|any }       // no specific types (union is all types)
-interface{ int; m() }          // int (but type set is empty because int has no method m)
-interface{ ~int; m() }         // int (but type set is infinite because many integer types have a method m)
-interface{ int; any }          // int
-interface{ int; string }       // no specific types (intersection is empty)
-</pre>
-
 <h3 id="Type_identity">Type identity</h3>
 
 <p>
@@ -1938,7 +1974,7 @@ A4, func(int, float64) *[]string, and A5
 B0 and C0
 D0[int, string] and E0
 []int and []int
-struct{ a, b *T5 } and struct{ a, b *T5 }
+struct{ a, b *B5 } and struct{ a, b *B5 }
 func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5
 </pre>
 
@@ -1958,27 +1994,28 @@ defined type while the latter is a type literal
 <h3 id="Assignability">Assignability</h3>
 
 <p>
-A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
+A value <code>x</code> of type <code>V</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
 ("<code>x</code> is assignable to <code>T</code>") if one of the following conditions applies:
 </p>
 
 <ul>
 <li>
-<code>x</code>'s type is identical to <code>T</code>.
+<code>V</code> and <code>T</code> are identical.
 </li>
 <li>
-<code>x</code>'s type <code>V</code> and <code>T</code> have identical
-<a href="#Underlying_types">underlying types</a> and at least one of <code>V</code>
+<code>V</code> and <code>T</code> have identical
+<a href="#Underlying_types">underlying types</a>
+but are not type parameters and at least one of <code>V</code>
 or <code>T</code> is not a <a href="#Types">named type</a>.
 </li>
 <li>
-<code>x</code>'s type <code>V</code> and <code>T</code> are channel types with
+<code>V</code> and <code>T</code> are channel types with
 identical element types, <code>V</code> is a bidirectional channel,
 and at least one of <code>V</code> or <code>T</code> is not a <a href="#Types">named type</a>.
 </li>
 <li>
 <code>T</code> is an interface type, but not a type parameter, and
-<code>x</code> <a href="#Interface_types">implements</a> <code>T</code>.
+<code>x</code> <a href="#Implementing_an_interface">implements</a> <code>T</code>.
 </li>
 <li>
 <code>x</code> is the predeclared identifier <code>nil</code> and <code>T</code>
@@ -1993,25 +2030,24 @@ by a value of type <code>T</code>.
 </ul>
 
 <p>
-Additionally, if <code>x's</code> type <code>V</code> or <code>T</code> are type parameters
-with <a href="#Specific_types">specific types</a>, <code>x</code>
+Additionally, if <code>x</code>'s type <code>V</code> or <code>T</code> are type parameters, <code>x</code>
 is assignable to a variable of type <code>T</code> if one of the following conditions applies:
 </p>
 
 <ul>
 <li>
 <code>x</code> is the predeclared identifier <code>nil</code>, <code>T</code> is
-a type parameter, and <code>x</code> is assignable to each specific type of
-<code>T</code>.
+a type parameter, and <code>x</code> is assignable to each type in
+<code>T</code>'s type set.
 </li>
 <li>
 <code>V</code> is not a <a href="#Types">named type</a>, <code>T</code> is
-a type parameter, and <code>x</code> is assignable to each specific type of
-<code>T</code>.
+a type parameter, and <code>x</code> is assignable to each type in
+<code>T</code>'s type set.
 </li>
 <li>
 <code>V</code> is a type parameter and <code>T</code> is not a named type,
-and values of each specific type of <code>V</code> are assignable
+and values of each type in <code>V</code>'s type set are assignable
 to <code>T</code>.
 </li>
 </ul>
@@ -2021,7 +2057,7 @@ to <code>T</code>.
 <p>
 A <a href="#Constants">constant</a> <code>x</code> is <i>representable</i>
 by a value of type <code>T</code>,
-where <code>T</code> is not a <a href="#Type_parameters">type parameter</a>,
+where <code>T</code> is not a <a href="#Type_parameter_declarations">type parameter</a>,
 if one of the following conditions applies:
 </p>
 
@@ -2046,9 +2082,9 @@ are representable by values of <code>T</code>'s component type (<code>float32</c
 </ul>
 
 <p>
-If <code>T</code> is a type parameter with <a href="#Specific_types">specific types</a>,
+If <code>T</code> is a type parameter,
 <code>x</code> is representable by a value of type <code>T</code> if <code>x</code> is representable
-by a value of each specific type of <code>T</code>.
+by a value of each type in <code>T</code>'s type set.
 </p>
 
 <pre>
@@ -2161,6 +2197,7 @@ Blocks nest and influence <a href="#Declarations_and_scope">scoping</a>.
 A <i>declaration</i> binds a non-<a href="#Blank_identifier">blank</a> identifier to a
 <a href="#Constant_declarations">constant</a>,
 <a href="#Type_declarations">type</a>,
+<a href="#Type_parameter_declarations">type parameter</a>,
 <a href="#Variable_declarations">variable</a>,
 <a href="#Function_declarations">function</a>,
 <a href="#Labeled_statements">label</a>, or
@@ -2205,13 +2242,12 @@ Go is lexically scoped using <a href="#Blocks">blocks</a>:
        <li>The scope of an identifier denoting a method receiver, function parameter,
            or result variable is the function body.</li>
 
-       <li>The scope of an identifier denoting a type parameter of a generic function
-           or declared by a method receiver is the function body and all parameter lists of the
-           function.
-       </li>
+       <li>The scope of an identifier denoting a type parameter of a function
+           or declared by a method receiver begins after the name of the function
+           and ends at the end of the function body.</li>
 
-       <li>The scope of an identifier denoting a type parameter of a generic type
-           begins after the name of the generic type and ends at the end
+       <li>The scope of an identifier denoting a type parameter of a type
+           begins after the name of the type and ends at the end
            of the TypeSpec.</li>
 
        <li>The scope of a constant or variable identifier declared
@@ -2259,7 +2295,7 @@ the body of any nested function.
 The <i>blank identifier</i> is represented by the underscore character <code>_</code>.
 It serves as an anonymous placeholder instead of a regular (non-blank)
 identifier and has special meaning in <a href="#Declarations_and_scope">declarations</a>,
-as an <a href="#Operands">operand</a>, and in <a href="#Assignments">assignments</a>.
+as an <a href="#Operands">operand</a>, and in <a href="#Assignment_statements">assignment statements</a>.
 </p>
 
 
@@ -2283,8 +2319,8 @@ Zero value:
        nil
 
 Functions:
-       append cap close complex copy delete imag len
-       make new panic print println real recover
+       append cap clear close complex copy delete imag len
+       make max min new panic print println real recover
 </pre>
 
 <h3 id="Exported_identifiers">Exported identifiers</h3>
@@ -2294,8 +2330,8 @@ An identifier may be <i>exported</i> to permit access to it from another package
 An identifier is exported if both:
 </p>
 <ol>
-       <li>the first character of the identifier's name is a Unicode upper case
-       letter (Unicode class "Lu"); and</li>
+       <li>the first character of the identifier's name is a Unicode uppercase
+       letter (Unicode character category Lu); and</li>
        <li>the identifier is declared in the <a href="#Blocks">package block</a>
        or it is a <a href="#Struct_types">field name</a> or
        <a href="#MethodName">method name</a>.</li>
@@ -2475,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>
 
@@ -2497,7 +2533,7 @@ type (
 
 type TreeNode struct {
        left, right *TreeNode
-       value *Comparable
+       value any
 }
 
 type Block interface {
@@ -2558,7 +2594,7 @@ func (tz TimeZone) String() string {
 </pre>
 
 <p>
-If the type definition specifies <a href="#Type_parameter_lists">type parameters</a>,
+If the type definition specifies <a href="#Type_parameter_declarations">type parameters</a>,
 the type name denotes a <i>generic type</i>.
 Generic types must be <a href="#Instantiations">instantiated</a> when they
 are used.
@@ -2569,15 +2605,10 @@ 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.
+In a type definition the given type cannot be a type parameter.
 </p>
 
 <pre>
@@ -2589,8 +2620,8 @@ func f[T any]() {
 </pre>
 
 <p>
-A generic type may also have methods associated with it. In this case,
-the method receivers must declare the same number of type parameters as
+A generic type may also have <a href="#Method_declarations">methods</a> associated with it.
+In this case, the method receivers must declare the same number of type parameters as
 present in the generic type definition.
 </p>
 
@@ -2599,11 +2630,10 @@ present in the generic type definition.
 func (l *List[T]) Len() int  { … }
 </pre>
 
-<h3 id="Type_parameter_lists">Type parameter lists</h3>
+<h3 id="Type_parameter_declarations">Type parameter declarations</h3>
 
 <p>
-A type parameter list declares the <a href="#Type_parameters">type parameters</a>
-in a generic function or type declaration.
+A type parameter list declares the <i>type parameters</i> of a generic 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.
@@ -2616,9 +2646,11 @@ 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>.
+Each name declares a type parameter, which is a new and different <a href="#Types">named type</a>
+that acts as a placeholder for an (as of yet) unknown type in the declaration.
+The type parameter is replaced with a <i>type argument</i> upon
+<a href="#Instantiations">instantiation</a> of the generic function or type.
 </p>
 
 <pre>
@@ -2637,22 +2669,22 @@ has a corresponding (meta-)type which is called its
 
 <p>
 A parsing ambiguity arises when the type parameter list for a generic type
-declares a single type parameter with a type constraint of the form <code>*C</code>
-or <code>(C)</code> where <code>C</code> is not a (possibly parenthesized)
-<a href="#Types">type literal</a>:
+declares a single type parameter <code>P</code> with a constraint <code>C</code>
+such that the text <code>P C</code> forms a valid expression:
 </p>
 
 <pre>
 type T[P *C] …
 type T[P (C)] …
+type T[P *C|Q] …
+…
 </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 or use a trailing
-comma:
+In these rare cases, the type parameter list is indistinguishable from an
+expression and the type declaration is parsed as an array type declaration.
+To resolve the ambiguity, embed the constraint in an
+<a href="#Interface_types">interface</a> or use a trailing comma:
 </p>
 
 <pre>
@@ -2660,10 +2692,32 @@ type T[P interface{*C}] …
 type T[P *C,] …
 </pre>
 
+<p>
+Type parameters may also be declared by the receiver specification
+of a <a href="#Method_declarations">method declaration</a> associated
+with a generic type.
+</p>
+
+<p>
+Within a type parameter list of a generic type <code>T</code>, a type constraint
+may not (directly, or indirectly through the type parameter list of another
+generic type) refer to <code>T</code>.
+</p>
+
+<pre>
+type T1[P T1[P]] …                    // illegal: T1 refers to itself
+type T2[P interface{ T2[int] }] …     // illegal: T2 refers to itself
+type T3[P interface{ m(T3[int])}] …   // illegal: T3 refers to itself
+type T4[P T5[P]] …                    // illegal: T4 refers to T5 and
+type T5[P T4[P]] …                    //          T5 refers to T4
+
+type T6[P int] struct{ f *T6[P] }     // ok: reference to T6 is not in type parameter list
+</pre>
+
 <h4 id="Type_constraints">Type constraints</h4>
 
 <p>
-A type constraint is an <a href="#Interface_types">interface</a> that defines the
+A <i>type constraint</i> is an <a href="#Interface_types">interface</a> that defines the
 set of permissible type arguments for the respective type parameter and controls the
 operations supported by values of that type parameter.
 </p>
@@ -2674,56 +2728,44 @@ TypeConstraint = TypeElem .
 
 <p>
 If the constraint is an interface literal of the form <code>interface{E}</code> where
-<code>E</code> is an embedded type element (not a method), in a type parameter list
+<code>E</code> is an embedded <a href="#Interface_types">type element</a> (not a method), 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
+[T []P]                      // = [T interface{[]P}]
+[T ~int]                     // = [T interface{~int}]
+[T int|string]               // = [T interface{int|string}]
+type Constraint ~int         // illegal: ~int is not in a type parameter list
 </pre>
 
 <!--
 We should be able to simplify the rules for comparable or delegate some of them
-elsewhere once we have a section that clearly defines how interfaces implement
+elsewhere since we have a section that clearly defines how interfaces implement
 other interfaces based on their type sets. But this should get us going for now.
 -->
 
 <p>
 The <a href="#Predeclared_identifiers">predeclared</a>
 <a href="#Interface_types">interface type</a> <code>comparable</code>
-denotes the set of all concrete (non-interface) types that are
-<a href="#Comparison_operators">comparable</a>. Specifically,
-a type <code>T</code> implements <code>comparable</code> if:
+denotes the set of all non-interface types that are
+<a href="#Comparison_operators">strictly comparable</a>.
 </p>
 
-<ul>
-<li>
-       <code>T</code> is not an interface type and <code>T</code> supports the operations
-       <code>==</code> and <code>!=</code>; or
-</li>
-<li>
-       <code>T</code> is an interface type and each type in <code>T</code>'s
-       <a href="#Interface_types">type set</a> implements <code>comparable</code>.
-</li>
-</ul>
-
 <p>
-Even though interfaces that are not type parameters can be
-<a href="#Comparison_operators">compared</a>
-(possibly causing a run-time panic) they do not implement
-<code>comparable</code>.
+Even though interfaces that are not type parameters are <a href="#Comparison_operators">comparable</a>,
+they are not strictly comparable and therefore they do not implement <code>comparable</code>.
+However, they <a href="#Satisfying_a_type_constraint">satisfy</a> <code>comparable</code>.
 </p>
 
 <pre>
-int                          // implements comparable
+int                          // implements comparable (int is strictly comparable)
 []byte                       // does not implement comparable (slices cannot be compared)
 interface{}                  // does not implement comparable (see above)
-interface{ ~int | ~string }  // type parameter only: implements comparable
-interface{ comparable }      // type parameter only: implements comparable
-interface{ ~int | ~[]byte }  // type parameter only: does not implement comparable (not all types in the type set are comparable)
+interface{ ~int | ~string }  // type parameter only: implements comparable (int, string types are strictly comparable)
+interface{ comparable }      // type parameter only: implements comparable (comparable implements itself)
+interface{ ~int | ~[]byte }  // type parameter only: does not implement comparable (slices are not comparable)
+interface{ ~struct{ any } }  // type parameter only: does not implement comparable (field any is not strictly comparable)
 </pre>
 
 <p>
@@ -2732,6 +2774,51 @@ The <code>comparable</code> interface and interfaces that (directly or indirectl
 values or variables, or components of other, non-interface types.
 </p>
 
+<h4 id="Satisfying_a_type_constraint">Satisfying a type constraint</h4>
+
+<p>
+A type argument <code>T</code><i> satisfies</i> a type constraint <code>C</code>
+if <code>T</code> is an element of the type set defined by <code>C</code>; i.e.,
+if <code>T</code> <a href="#Implementing_an_interface">implements</a> <code>C</code>.
+As an exception, a <a href="#Comparison_operators">strictly comparable</a>
+type constraint may also be satisfied by a <a href="#Comparison_operators">comparable</a>
+(not necessarily strictly comparable) type argument.
+More precisely:
+</p>
+
+<p>
+A type T <i>satisfies</i> a constraint <code>C</code> if
+</p>
+
+<ul>
+<li>
+       <code>T</code> <a href="#Implementing_an_interface">implements</a> <code>C</code>; or
+</li>
+<li>
+       <code>C</code> can be written in the form <code>interface{ comparable; E }</code>,
+       where <code>E</code> is a <a href="#Basic_interfaces">basic interface</a> and
+       <code>T</code> is <a href="#Comparison_operators">comparable</a> and implements <code>E</code>.
+</li>
+</ul>
+
+<pre>
+type argument      type constraint                // constraint satisfaction
+
+int                interface{ ~int }              // satisfied: int implements interface{ ~int }
+string             comparable                     // satisfied: string implements comparable (string is strictly comparable)
+[]byte             comparable                     // not satisfied: slices are not comparable
+any                interface{ comparable; int }   // not satisfied: any does not implement interface{ int }
+any                comparable                     // satisfied: any is comparable and implements the basic interface any
+struct{f any}      comparable                     // satisfied: struct{f any} is comparable and implements the basic interface any
+any                interface{ comparable; m() }   // not satisfied: any does not implement the basic interface interface{ m() }
+interface{ m() }   interface{ comparable; m() }   // satisfied: interface{ m() } is comparable and implements the basic interface interface{ m() }
+</pre>
+
+<p>
+Because of the exception in the constraint satisfaction rule, comparing operands of type parameter type
+may panic at run-time (even though comparable type parameters are always strictly comparable).
+</p>
+
 <h3 id="Variable_declarations">Variable declarations</h3>
 
 <p>
@@ -2759,7 +2846,7 @@ var _, found = entries[name]  // map lookup; only interested in "found"
 
 <p>
 If a list of expressions is given, the variables are initialized
-with the expressions following the rules for <a href="#Assignments">assignments</a>.
+with the expressions following the rules for <a href="#Assignment_statements">assignment statements</a>.
 Otherwise, each variable is initialized to its <a href="#The_zero_value">zero value</a>.
 </p>
 
@@ -2803,7 +2890,7 @@ with initializer expressions but no types:
 </p>
 
 <pre class="grammar">
-"var" IdentifierList = ExpressionList .
+"var" IdentifierList "=" ExpressionList .
 </pre>
 
 <pre>
@@ -2821,12 +2908,14 @@ variables provided they were originally declared earlier in the same block
 and at least one of the non-<a href="#Blank_identifier">blank</a> variables is new.
 As a consequence, redeclaration can only appear in a multi-variable short declaration.
 Redeclaration does not introduce a new variable; it just assigns a new value to the original.
+The non-blank variable names on the left side of <code>:=</code>
+must be <a href="#Uniqueness_of_identifiers">unique</a>.
 </p>
 
 <pre>
 field1, offset := nextField(str, 0)
 field2, offset := nextField(str, offset)  // redeclares offset
-a, a := 1, 2                              // illegal: double declaration of a or no new variable if a was declared elsewhere
+x, y, x := 1, 2, 3                        // illegal: x repeated on left side of :=
 </pre>
 
 <p>
@@ -2875,14 +2964,14 @@ func IndexRune(s string, r rune) int {
 </pre>
 
 <p>
-If the function declaration specifies <a href="#Type_parameter_lists">type parameters</a>,
+If the function declaration specifies <a href="#Type_parameter_declarations">type parameters</a>,
 the function name denotes a <i>generic function</i>.
-Generic functions must be <a href="#Instantiations">instantiated</a> when they
-are used.
+A generic function must be <a href="#Instantiations">instantiated</a> before it can be
+called or used as a value.
 </p>
 
 <pre>
-func min[T constraints.Ordered](x, y T) T {
+func min[T ~int|~float64](x, y T) T {
        if x &lt; y {
                return x
        }
@@ -2941,7 +3030,7 @@ the non-blank method and field names must be distinct.
 </p>
 
 <p>
-Given defined type <code>Point</code>, the declarations
+Given defined type <code>Point</code> the declarations
 </p>
 
 <pre>
@@ -2965,13 +3054,10 @@ to the base type <code>Point</code>.
 If the receiver base type is a <a href="#Type_declarations">generic type</a>, the
 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="#Instantiations">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.
+<a href="#Instantiations">instantiation</a> of the receiver base type: the type
+arguments must be identifiers denoting 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.
@@ -2985,8 +3071,8 @@ type Pair[A, B any] struct {
        b B
 }
 
-func (p Pair[A, B]) Swap() Pair[B, A]  { return Pair[B, A]{p.b, p.a} }
-func (p Pair[First, _]) First() First  { return p.a }
+func (p Pair[A, B]) Swap() Pair[B, A]  { … }  // receiver declares A, B
+func (p Pair[First, _]) First() First  { … }  // receiver declares First, corresponds to A in Pair
 </pre>
 
 <h2 id="Expressions">Expressions</h2>
@@ -3023,7 +3109,15 @@ resulting operand is an <a href="#Instantiations">instantiated</a> function.
 
 <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>.
+operand only on the left-hand side of an <a href="#Assignment_statements">assignment statement</a>.
+</p>
+
+<p>
+Implementation restriction: A compiler need not report an error if an operand's
+type is a <a href="#Type_parameter_declarations">type parameter</a> with an empty
+<a href="#Interface_types">type set</a>. Functions with such type parameters
+cannot be <a href="#Instantiations">instantiated</a>; any attempt will lead
+to an error at the instantiation site.
 </p>
 
 <h3 id="Qualified_identifiers">Qualified identifiers</h3>
@@ -3046,7 +3140,7 @@ declared in the <a href="#Blocks">package block</a> of that package.
 </p>
 
 <pre>
-math.Sin       // denotes the Sin function in package math
+math.Sin // denotes the Sin function in package math
 </pre>
 
 <h3 id="Composite_literals">Composite literals</h3>
@@ -3060,7 +3154,7 @@ Each element may optionally be preceded by a corresponding key.
 <pre class="ebnf">
 CompositeLit  = LiteralType LiteralValue .
 LiteralType   = StructType | ArrayType | "[" "..." "]" ElementType |
-                SliceType | MapType | TypeName .
+                SliceType | MapType | TypeName [ TypeArgs ] .
 LiteralValue  = "{" [ ElementList [ "," ] ] "}" .
 ElementList   = KeyedElement { "," KeyedElement } .
 KeyedElement  = [ Key ":" ] Element .
@@ -3072,7 +3166,7 @@ Element       = Expression | LiteralValue .
 <p>
 The LiteralType's <a href="#Core_types">core type</a> <code>T</code>
 must be a struct, array, slice, or map type
-(the grammar enforces this constraint except when the type is given
+(the syntax enforces this constraint except when the type is given
 as a TypeName).
 The types of the elements and keys must be <a href="#Assignability">assignable</a>
 to the respective field, element, and key types of type <code>T</code>;
@@ -3309,7 +3403,7 @@ PrimaryExpr =
        PrimaryExpr Arguments .
 
 Selector       = "." identifier .
-Index          = "[" Expression "]" .
+Index          = "[" Expression [ "," ] "]" .
 Slice          = "[" [ Expression ] ":" [ Expression ] "]" |
                  "[" [ Expression ] ":" Expression ":" Expression "]" .
 TypeAssertion  = "." "(" Type ")" .
@@ -3332,8 +3426,6 @@ f.p[i].x()
 
 <h3 id="Selectors">Selectors</h3>
 
-<!-- This is missing rules for x of type parameter type. -->
-
 <p>
 For a <a href="#Primary_expressions">primary expression</a> <code>x</code>
 that is not a <a href="#Package_clause">package name</a>, the
@@ -3734,7 +3826,7 @@ The following rules apply:
 </p>
 
 <p>
-If <code>a</code> is not a map:
+If <code>a</code> is neither a map nor a type parameter:
 </p>
 <ul>
        <li>the index <code>x</code> must be an untyped constant or its
@@ -3803,23 +3895,22 @@ For <code>a</code> of <a href="#Map_types">map type</a> <code>M</code>:
 </ul>
 
 <p>
-For <code>a</code> of <a href="#Type_parameters">type parameter type</a> <code>P</code>:
+For <code>a</code> of <a href="#Type_parameter_declarations">type parameter type</a> <code>P</code>:
 </p>
 <ul>
-       <li><code>P</code> must have <a href="#Specific_types">specific types</a>.</li>
        <li>The index expression <code>a[x]</code> must be valid for values
-           of all specific types of <code>P</code>.</li>
-       <li>The element types of all specific types of <code>P</code> must be identical.
+           of all types in <code>P</code>'s type set.</li>
+       <li>The element types of all types in <code>P</code>'s type set must be identical.
            In this context, the element type of a string type is <code>byte</code>.</li>
-       <li>If there is a map type among the specific types of <code>P</code>,
-           all specific types must be map types, and the respective key types
+       <li>If there is a map type in the type set of <code>P</code>,
+           all types in that type set must be map types, and the respective key types
            must be all identical.</li>
        <li><code>a[x]</code> is the array, slice, or string element at index <code>x</code>,
            or the map element with key <code>x</code> of the type argument
            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 the specific types of <code>P</code>
-           include string types.
+       <li><code>a[x]</code> may not be assigned to if <code>P</code>'s type set
+           includes string types.</li>
 </ul>
 
 <p>
@@ -3828,7 +3919,7 @@ Otherwise <code>a[x]</code> is illegal.
 
 <p>
 An index expression on a map <code>a</code> of type <code>map[K]V</code>
-used in an <a href="#Assignments">assignment</a> or initialization of the special form
+used in an <a href="#Assignment_statements">assignment statement</a> or initialization of the special form
 </p>
 
 <pre>
@@ -3869,7 +3960,8 @@ a[low : high]
 
 <p>
 constructs a substring or slice. The <a href="#Core_types">core type</a> of
-<code>a</code> must be a string, array, pointer to array, or slice.
+<code>a</code> must be a string, array, pointer to array, slice, or a
+<a href="#Core_types"><code>bytestring</code></a>.
 The <i>indices</i> <code>low</code> and
 <code>high</code> select which elements of operand <code>a</code> appear
 in the result. The result has indices starting at 0 and length equal to
@@ -3940,6 +4032,9 @@ var a [10]int
 s1 := a[3:7]   // underlying array of s1 is array a; &amp;s1[2] == &amp;a[5]
 s2 := s1[1:4]  // underlying array of s2 is underlying array of s1 which is array a; &amp;s2[1] == &amp;a[5]
 s2[1] = 42     // s2[1] == s1[2] == a[5] == 42; they all refer to the same underlying array element
+
+var s []int
+s3 := s[:0]    // s3 == nil
 </pre>
 
 
@@ -3997,7 +4092,7 @@ If the indices are out of range at run time, a <a href="#Run_time_panics">run-ti
 
 <p>
 For an expression <code>x</code> of <a href="#Interface_types">interface type</a>,
-but not a <a href="#Type_parameters">type parameter</a>, and a type <code>T</code>,
+but not a <a href="#Type_parameter_declarations">type parameter</a>, and a type <code>T</code>,
 the primary expression
 </p>
 
@@ -4018,7 +4113,7 @@ In this case, <code>T</code> must <a href="#Method_sets">implement</a> the (inte
 otherwise the type assertion is invalid since it is not possible for <code>x</code>
 to store a value of type <code>T</code>.
 If <code>T</code> is an interface type, <code>x.(T)</code> asserts that the dynamic type
-of <code>x</code> implements the interface <code>T</code>.
+of <code>x</code> <a href="#Implementing_an_interface">implements</a> the interface <code>T</code>.
 </p>
 <p>
 If the type assertion holds, the value of the expression is the value
@@ -4043,7 +4138,7 @@ func f(y I) {
 </pre>
 
 <p>
-A type assertion used in an <a href="#Assignments">assignment</a> or initialization of the special form
+A type assertion used in an <a href="#Assignment_statements">assignment statement</a> or initialization of the special form
 </p>
 
 <pre>
@@ -4212,7 +4307,7 @@ with the same underlying array.
 <p>
 A generic function or type is <i>instantiated</i> by substituting <i>type arguments</i>
 for the type parameters.
-Instantiation proceeds in two phases:
+Instantiation proceeds in two steps:
 </p>
 
 <ol>
@@ -4224,8 +4319,8 @@ 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)
+After substitution, each type argument must <a href="#Satisfying_a_type_constraint">satisfy</a>
+the <a href="#Type_parameter_declarations">constraint</a> (instantiated, if necessary)
 of the corresponding type parameter. Otherwise instantiation fails.
 </li>
 </ol>
@@ -4238,430 +4333,396 @@ instantiating a function produces a new non-generic function.
 <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>
-Generic types, and generic 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 generic 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
+[P any]                int               int satisfies any
+[S ~[]E, E any]        []int, int        []int satisfies ~[]int, int satisfies any
+[P io.Writer]          string            illegal: string doesn't satisfy io.Writer
+[P comparable]         any               any satisfies (but does not implement) comparable
 </pre>
 
-<h3 id="Type_inference">Type inference</h3>
-
-<p>
-Missing 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 implements 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
+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 <a href="#Type_parameter_lists">type parameter list</a>
+       <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 substitution map <i>M</i> initialized with the known type arguments, if any
+       <a href="#Calls">passed as an argument</a> to another function, or
 </li>
 <li>
-       a (possibly empty) list of ordinary function arguments (in case of a function call only)
+       <a href="#Return_statements">returned as a result</a>.
 </li>
 </ul>
 
 <p>
-and then proceeds with the following steps:
+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>
 
-<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>
+<pre>
+// sum returns the sum (concatenation, for strings) of its arguments.
+func sum[T ~int | ~float64 | ~string](x... T) T { … }
 
-<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>
+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>
-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.
+A partial type argument list cannot be empty; at least the first argument must be present.
+The list is 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>
 
-<h4 id="Type_unification">Type unification</h3>
+<pre>
+func apply[S ~[]E, E any](s S, f func(E) E) S { … }
 
-<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>
+f0 := apply[]                  // illegal: type argument list cannot be empty
+f1 := apply[[]int]             // type argument for S explicitly provided, type argument for E inferred
+f2 := apply[[]string, string]  // both type arguments explicitly provided
 
-<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.
-</p>
+var bytes []byte
+r := apply(bytes, func(byte) byte { … })  // both type arguments inferred from the function arguments
+</pre>
 
 <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.
+For a generic type, all type arguments must always be provided explicitly.
 </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.
--->
+<h3 id="Type_inference">Type inference</h3>
 
 <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:
+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>
 
-<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
+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>
 
-<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
+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>
-type Vector []float64
-</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.
+For example, given
 </p>
 
-<h4 id="Function_argument_type_inference">Function argument type inference</h3>
-
-<!-- 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. -->
+<pre>
+// dedup returns a copy of the argument slice with any duplicate entries removed.
+func dedup[S ~[]E, E comparable](S) S { … }
 
-<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>
+type Slice []int
+var s Slice
+s = dedup(s)   // same as s = dedup[Slice, int](s)
+</pre>
 
 <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>
-Function argument type inference can be used when the function has ordinary parameters
-whose types are defined using the function's type parameters. 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>
-Example:
-</p>
-
-<pre>
-func min[T constraints.Ordered](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)
-</pre>
-
-<h4 id="Constraint_type_inference">Constraint type inference</h3>
-
-<!--
-       The next paragraph needs to be updated for the new definition of core type:
-       The core type of an interface is the single underlying type of its type set,
-       if it exists. But for constraint type inference, if the type set consists of exactly
-       one type, we want to use that one type (which may be a defined type, different from
-       its underlying == core type).
--->
-
-<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>.
-</p>
-
-<p>
-For instance, consider the type parameter list with type parameters <code>List</code> and
-<code>Elem</code>:
+If not all type arguments have been found after these two phases, type inference fails.
 </p>
 
-<pre>
-[List ~[]Elem, Elem any]
-</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>:
+If the two phases are successful, type inference determined a type argument for each
+bound type parameter:
 </p>
 
 <pre>
-type Bytes []byte
+       P<sub>k</sub> ➞ A<sub>k</sub>
 </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.
+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>
-Generally, constraint type inference proceeds in two phases: Starting with a given
-substitution map <i>M</i>
+If type arguments contain cyclic references to themselves
+through bound type parameters, simplification and thus type
+inference fails.
+Otherwise, type inference succeeds.
 </p>
 
-<ol>
-<li>
-For all type parameters with a core type, unify the type parameter with the core
-type. If any unification fails, constraint type inference fails.
-</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.
-</li>
-</ol>
+<h4 id="Type_unification">Type unification</h4>
 
 <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>.
+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, given the type parameter list
+For example, given the type equation with the bound type parameter
+<code>P</code>
 </p>
 
 <pre>
-[A any, B []C, C *A]
+       [10]struct{ elem P, list []P } ≡<sub>A</sub> [10]struct{ elem string; list []string }
 </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:
+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>
 
 <p>
-<code>A</code> &RightArrow; <code>int</code>,
-<code>B</code> &RightArrow; <code>[]C</code>,
-<code>C</code> &RightArrow; <code>*A</code>
+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>
-Replace <code>A</code> on the right-hand side of &RightArrow; with <code>int</code>:
+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>
-<code>A</code> &RightArrow; <code>int</code>,
-<code>B</code> &RightArrow; <code>[]C</code>,
-<code>C</code> &RightArrow; <code>*int</code>
+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>
 
-<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>
+<li>
+       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>
+       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>
+</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>
@@ -4742,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
@@ -4764,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>
 
 
@@ -4800,9 +4863,8 @@ The bitwise logical and shift operators apply to integers only.
 </pre>
 
 <p>
-Excluding shifts, if the operand type is a <a href="#Type_parameters">type parameter</a>,
-it must have <a href="#Specific_types">specific types</a>, and the operator must
-apply to each specific type.
+If the operand type is a <a href="#Type_parameter_declarations">type parameter</a>,
+the operator must apply to each type in that type set.
 The operands are represented as values of the type argument that the type parameter
 is <a href="#Instantiations">instantiated</a> with, and the operation is computed
 with the precision of that type argument. For example, given the function:
@@ -4820,16 +4882,11 @@ func dotProduct[F ~float32|~float64](v1, v2 []F) F {
 </pre>
 
 <p>
-the the product <code>x * y</code> and the addition <code>s += x * y</code>
+the product <code>x * y</code> and the addition <code>s += x * y</code>
 are computed with <code>float32</code> or <code>float64</code> precision,
 respectively, depending on the type argument for <code>F</code>.
 </p>
 
-<p>
-For shifts, the <a href="#Core_types">core type</a> of both operands must be
-an integer.
-</p>
-
 <h4 id="Integer_operators">Integer operators</h4>
 
 <p>
@@ -4863,7 +4920,7 @@ due to two's-complement <a href="#Integer_overflow">integer overflow</a>:
 </p>
 
 <pre>
-                        x, q
+                         x, q
 int8                     -128
 int16                  -32768
 int32             -2147483648
@@ -5010,89 +5067,99 @@ to the type of the second operand, or vice versa.
 </p>
 <p>
 The equality operators <code>==</code> and <code>!=</code> apply
-to operands that are <i>comparable</i>.
+to operands of <i>comparable</i> types.
 The ordering operators <code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, and <code>&gt;=</code>
-apply to operands that are <i>ordered</i>.
+apply to operands of <i>ordered</i> types.
 These terms and the result of the comparisons are defined as follows:
 </p>
 
 <ul>
        <li>
-       Boolean values are comparable.
+       Boolean types are comparable.
        Two boolean values are equal if they are either both
        <code>true</code> or both <code>false</code>.
        </li>
 
        <li>
-       Integer values are comparable and ordered, in the usual way.
+       Integer types are comparable and ordered.
+       Two integer values are compared in the usual way.
        </li>
 
        <li>
-       Floating-point values are comparable and ordered,
-       as defined by the IEEE-754 standard.
+       Floating-point types are comparable and ordered.
+       Two floating-point values are compared as defined by the IEEE-754 standard.
        </li>
 
        <li>
-       Complex values are comparable.
+       Complex types are comparable.
        Two complex values <code>u</code> and <code>v</code> are
        equal if both <code>real(u) == real(v)</code> and
        <code>imag(u) == imag(v)</code>.
        </li>
 
        <li>
-       String values are comparable and ordered, lexically byte-wise.
+       String types are comparable and ordered.
+       Two string values are compared lexically byte-wise.
        </li>
 
        <li>
-       Pointer values are comparable.
+       Pointer types are comparable.
        Two pointer values are equal if they point to the same variable or if both have value <code>nil</code>.
        Pointers to distinct <a href="#Size_and_alignment_guarantees">zero-size</a> variables may or may not be equal.
        </li>
 
        <li>
-       Channel values are comparable.
+       Channel types are comparable.
        Two channel values are equal if they were created by the same call to
        <a href="#Making_slices_maps_and_channels"><code>make</code></a>
        or if both have value <code>nil</code>.
        </li>
 
        <li>
-       Interface values are comparable.
+       Interface types that are not type parameters are comparable.
        Two interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types
        and equal dynamic values or if both have value <code>nil</code>.
        </li>
 
        <li>
        A value <code>x</code> of non-interface type <code>X</code> and
-       a value <code>t</code> of interface type <code>T</code> are comparable when values
-       of type <code>X</code> are comparable and
-       <code>X</code> implements <code>T</code>.
+       a value <code>t</code> of interface type <code>T</code> can be compared
+       if type <code>X</code> is comparable and
+       <code>X</code> <a href="#Implementing_an_interface">implements</a> <code>T</code>.
        They are equal if <code>t</code>'s dynamic type is identical to <code>X</code>
        and <code>t</code>'s dynamic value is equal to <code>x</code>.
        </li>
 
        <li>
-       Struct values are comparable if all their fields are comparable.
+       Struct types are comparable if all their field types are comparable.
        Two struct values are equal if their corresponding
-       non-<a href="#Blank_identifier">blank</a> fields are equal.
+       non-<a href="#Blank_identifier">blank</a> field values are equal.
+       The fields are compared in source order, and comparison stops as
+       soon as two field values differ (or all fields have been compared).
        </li>
 
        <li>
-       Array values are comparable if values of the array element type are comparable.
-       Two array values are equal if their corresponding elements are equal.
+       Array types are comparable if their array element types are comparable.
+       Two array values are equal if their corresponding element values are equal.
+       The elements are compared in ascending index order, and comparison stops
+       as soon as two element values differ (or all elements have been compared).
        </li>
-</ul>
+
+       <li>
+       Type parameters are comparable if they are strictly comparable (see below).
+       </li>
+</ul>
 
 <p>
 A comparison of two interface values with identical dynamic types
-causes a <a href="#Run_time_panics">run-time panic</a> if values
-of that type are not comparable.  This behavior applies not only to direct interface
+causes a <a href="#Run_time_panics">run-time panic</a> if that type
+is not comparable.  This behavior applies not only to direct interface
 value comparisons but also when comparing arrays of interface values
 or structs with interface-valued fields.
 </p>
 
 <p>
-Slice, map, and function values are not comparable.
+Slice, map, and function types are not comparable.
 However, as a special case, a slice, map, or function value may
 be compared to the predeclared identifier <code>nil</code>.
 Comparison of pointer, channel, and interface values to <code>nil</code>
@@ -5113,12 +5180,36 @@ var (
 )
 </pre>
 
+<p>
+A type is <i>strictly comparable</i> if it is comparable and not an interface
+type nor composed of interface types.
+Specifically:
+</p>
+
+<ul>
+       <li>
+       Boolean, numeric, string, pointer, and channel types are strictly comparable.
+       </li>
+
+       <li>
+       Struct types are strictly comparable if all their field types are strictly comparable.
+       </li>
+
+       <li>
+       Array types are strictly comparable if their array element types are strictly comparable.
+       </li>
+
+       <li>
+       Type parameters are strictly comparable if all types in their type set are strictly comparable.
+       </li>
+</ul>
+
 <h3 id="Logical_operators">Logical operators</h3>
 
 <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">
@@ -5188,7 +5279,7 @@ f(&lt;-ch)
 </pre>
 
 <p>
-A receive expression used in an <a href="#Assignments">assignment</a> or initialization of the special form
+A receive expression used in an <a href="#Assignment_statements">assignment statement</a> or initialization of the special form
 </p>
 
 <pre>
@@ -5255,7 +5346,7 @@ as for non-constant <code>x</code>.
 </p>
 
 <p>
-Converting a constant to a type that is not a <a href="#Type_parameters">type parameter</a>
+Converting a constant to a type that is not a <a href="#Type_parameter_declarations">type parameter</a>
 yields a typed constant.
 </p>
 
@@ -5267,7 +5358,7 @@ float32(0.49999999)      // 0.5 of type float32
 float64(-1e-1000)        // 0.0 of type float64
 string('x')              // "x" of type string
 string(0x266c)           // "♬" of type string
-MyString("foo" + "bar")  // "foobar" of type MyString
+myString("foo" + "bar")  // "foobar" of type myString
 string([]byte{'a'})      // not a constant: []byte{'a'} is not a constant
 (*int)(nil)              // not a constant: nil is not a constant, *int is not a boolean, numeric, or string type
 int(1.2)                 // illegal: 1.2 cannot be represented as an int
@@ -5310,8 +5401,8 @@ in any of these cases:
        <li>
        ignoring struct tags (see below),
        <code>x</code>'s type and <code>T</code> are not
-       <a href="#Type_parameters">type parameters</a> but have
-       <a href="#Type_identity">identical</a> <a href="#Types">underlying types</a>.
+       <a href="#Type_parameter_declarations">type parameters</a> but have
+       <a href="#Type_identity">identical</a> <a href="#Underlying_types">underlying types</a>.
        </li>
        <li>
        ignoring struct tags (see below),
@@ -5335,30 +5426,30 @@ in any of these cases:
        <code>x</code> is a string and <code>T</code> is a slice of bytes or runes.
        </li>
        <li>
-       <code>x</code> is a slice, <code>T</code> is a pointer to an array,
+       <code>x</code> is a slice, <code>T</code> is an array or a pointer to an array,
        and the slice and array types have <a href="#Type_identity">identical</a> element types.
        </li>
 </ul>
 
 <p>
-Additionally, if <code>T</code> or </code><code>x's</code> type <code>V</code> are type
-parameters with <a href="#Specific_types">specific types</a>, <code>x</code>
+Additionally, if <code>T</code> or <code>x</code>'s type <code>V</code> are type
+parameters, <code>x</code>
 can also be converted to type <code>T</code> if one of the following conditions applies:
 </p>
 
 <ul>
 <li>
 Both <code>V</code> and <code>T</code> are type parameters and a value of each
-specific type of <code>V</code> can be converted to each specific type
-of <code>T</code>.
+type in <code>V</code>'s type set can be converted to each type in <code>T</code>'s
+type set.
 </li>
 <li>
 Only <code>V</code> is a type parameter and a value of each
-specific type of <code>V</code> can be converted to <code>T</code>.
+type in <code>V</code>'s type set can be converted to <code>T</code>.
 </li>
 <li>
 Only <code>T</code> is a type parameter and <code>x</code> can be converted to each
-specific type of <code>T</code>.
+type in <code>T</code>'s type set.
 </li>
 </ul>
 
@@ -5399,8 +5490,7 @@ of <code>x</code>.
 <p>
 There is no linguistic mechanism to convert between pointers and integers.
 The package <a href="#Package_unsafe"><code>unsafe</code></a>
-implements this functionality under
-restricted circumstances.
+implements this functionality under restricted circumstances.
 </p>
 
 <h4>Conversions between numeric types</h4>
@@ -5442,20 +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.
@@ -5465,8 +5541,12 @@ string([]byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'})   // "hellø"
 string([]byte{})                                     // ""
 string([]byte(nil))                                  // ""
 
-type MyBytes []byte
-string(MyBytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'})  // "hellø"
+type bytes []byte
+string(bytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'})    // "hellø"
+
+type myByte byte
+string([]myByte{'w', 'o', 'r', 'l', 'd', '!'})       // "world!"
+myString([]myByte{'\xf0', '\x9f', '\x8c', '\x8d'})   // "🌍"
 </pre>
 </li>
 
@@ -5480,20 +5560,27 @@ string([]rune{0x767d, 0x9d6c, 0x7fd4})   // "\u767d\u9d6c\u7fd4" == "白鵬翔"
 string([]rune{})                         // ""
 string([]rune(nil))                      // ""
 
-type MyRunes []rune
-string(MyRunes{0x767d, 0x9d6c, 0x7fd4})  // "\u767d\u9d6c\u7fd4" == "白鵬翔"
+type runes []rune
+string(runes{0x767d, 0x9d6c, 0x7fd4})    // "\u767d\u9d6c\u7fd4" == "白鵬翔"
+
+type myRune rune
+string([]myRune{0x266b, 0x266c})         // "\u266b\u266c" == "♫♬"
+myString([]myRune{0x1f30e})              // "\U0001f30e" == "🌎"
 </pre>
 </li>
 
 <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'}
-[]byte("")        // []byte{}
+[]byte("hellø")             // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
+[]byte("")                  // []byte{}
+
+bytes("hellø")              // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
 
-MyBytes("hellø")  // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
+[]myByte("world!")          // []myByte{'w', 'o', 'r', 'l', 'd', '!'}
+[]myByte(myString("🌏"))    // []myByte{'\xf0', '\x9f', '\x8c', '\x8f'}
 </pre>
 </li>
 
@@ -5502,32 +5589,68 @@ Converting a value of a string type to a slice of runes type
 yields a slice containing the individual Unicode code points of the string.
 
 <pre>
-[]rune(MyString("白鵬翔"))  // []rune{0x767d, 0x9d6c, 0x7fd4}
-[]rune("")                 // []rune{}
+[]rune(myString("白鵬翔"))   // []rune{0x767d, 0x9d6c, 0x7fd4}
+[]rune("")                  // []rune{}
 
-MyRunes("白鵬翔")           // []rune{0x767d, 0x9d6c, 0x7fd4}
+runes("白鵬翔")              // []rune{0x767d, 0x9d6c, 0x7fd4}
+
+[]myRune("♫♬")              // []myRune{0x266b, 0x266c}
+[]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_pointer">Conversions from slice to array pointer</h4>
+<h4 id="Conversions_from_slice_to_array_or_array_pointer">Conversions from slice to array or array pointer</h4>
 
 <p>
-Converting a slice to an array pointer yields a pointer to the underlying array of the slice.
-If the <a href="#Length_and_capacity">length</a> of the slice is less than the length of the array,
+Converting a slice to an array yields an array containing the elements of the underlying array of the slice.
+Similarly, converting a slice to an array pointer yields a pointer to the underlying array of the slice.
+In both cases, if the <a href="#Length_and_capacity">length</a> of the slice is less than the length of the array,
 a <a href="#Run_time_panics">run-time panic</a> occurs.
 </p>
 
 <pre>
 s := make([]byte, 2, 4)
+
+a0 := [0]byte(s)
+a1 := [1]byte(s[1:])     // a1[0] == s[1]
+a2 := [2]byte(s)         // a2[0] == s[0]
+a4 := [4]byte(s)         // panics: len([4]byte) > len(s)
+
 s0 := (*[0]byte)(s)      // s0 != nil
 s1 := (*[1]byte)(s[1:])  // &amp;s1[0] == &amp;s[1]
 s2 := (*[2]byte)(s)      // &amp;s2[0] == &amp;s[0]
 s4 := (*[4]byte)(s)      // panics: len([4]byte) > len(s)
 
 var t []string
-t0 := (*[0]string)(t)    // t0 == nil
-t1 := (*[1]string)(t)    // panics: len([1]string) > len(t)
+t0 := [0]string(t)       // ok for nil slice t
+t1 := (*[0]string)(t)    // t1 == nil
+t2 := (*[1]string)(t)    // panics: len([1]string) > len(t)
 
 u := make([]byte, 0)
 u0 := (*[0]byte)(u)      // u0 != nil
@@ -5664,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>
@@ -5866,7 +5993,7 @@ The following built-in functions are not permitted in statement context:
 
 <pre>
 append cap complex imag len make new real
-unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice
+unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice unsafe.SliceData unsafe.String unsafe.StringData
 </pre>
 
 <pre>
@@ -5922,7 +6049,7 @@ IncDecStmt = Expression ( "++" | "--" ) .
 </pre>
 
 <p>
-The following <a href="#Assignments">assignment statements</a> are semantically
+The following <a href="#Assignment_statements">assignment statements</a> are semantically
 equivalent:
 </p>
 
@@ -5933,7 +6060,14 @@ x--                 x -= 1
 </pre>
 
 
-<h3 id="Assignments">Assignments</h3>
+<h3 id="Assignment_statements">Assignment statements</h3>
+
+<p>
+An <i>assignment</i> replaces the current value stored in a <a href="#Variables">variable</a>
+with a new value specified by an <a href="#Expressions">expression</a>.
+An assignment statement may assign a single value to a single variable, or multiple values to a
+matching number of variables.
+</p>
 
 <pre class="ebnf">
 Assignment = ExpressionList assign_op ExpressionList .
@@ -6041,7 +6175,7 @@ x = []int{3, 5, 7}
 for i, x[i] = range x {  // set i, x[2] = 0, x[0]
        break
 }
-// after this loop, i == 0 and x == []int{3, 5, 3}
+// after this loop, i == 0 and x is []int{3, 5, 3}
 </pre>
 
 <p>
@@ -6230,7 +6364,7 @@ switch x.(type) {
 Cases then match actual types <code>T</code> against the dynamic type of the
 expression <code>x</code>. As with type assertions, <code>x</code> must be of
 <a href="#Interface_types">interface type</a>, but not a
-<a href="#Type_parameters">type parameter</a>, and each non-interface type
+<a href="#Type_parameter_declarations">type parameter</a>, and each non-interface type
 <code>T</code> listed in a case must implement the type of <code>x</code>.
 The types listed in the cases of a type switch must all be
 <a href="#Type_identity">different</a>.
@@ -6312,7 +6446,7 @@ if v == nil {
 </pre>
 
 <p>
-A <a href="#Type_parameters">type parameter</a> or a <a href="#Type_declarations">generic type</a>
+A <a href="#Type_parameter_declarations">type parameter</a> or a <a href="#Type_declarations">generic type</a>
 may be used as a type in a case. If upon <a href="#Instantiations">instantiation</a> that type turns
 out to duplicate another entry in the switch, the first matching case is chosen.
 </p>
@@ -6418,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>
 
@@ -6430,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>
@@ -6460,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>
@@ -6498,11 +6634,17 @@ 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>
 The iteration values are assigned to the respective
-iteration variables as in an <a href="#Assignments">assignment statement</a>.
+iteration variables as in an <a href="#Assignment_statements">assignment statement</a>.
 </p>
 
 <p>
@@ -6550,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>
 
 
@@ -6837,7 +6985,8 @@ OuterLoop:
 
 <p>
 A "continue" statement begins the next iteration of the
-innermost <a href="#For_statements">"for" loop</a> at its post statement.
+innermost enclosing <a href="#For_statements">"for" loop</a>
+by advancing control to the end of the loop block.
 The "for" loop must be within the same function.
 </p>
 
@@ -7012,6 +7161,121 @@ so they can only appear in <a href="#Calls">call expressions</a>;
 they cannot be used as function values.
 </p>
 
+
+<h3 id="Appending_and_copying_slices">Appending to and copying slices</h3>
+
+<p>
+The built-in functions <code>append</code> and <code>copy</code> assist in
+common slice operations.
+For both functions, the result is independent of whether the memory referenced
+by the arguments overlaps.
+</p>
+
+<p>
+The <a href="#Function_types">variadic</a> function <code>append</code>
+appends zero or more values <code>x</code> to a slice <code>s</code>
+and returns the resulting slice of the same type as <code>s</code>.
+The <a href="#Core_types">core type</a> of <code>s</code> must be a slice
+of type <code>[]E</code>.
+The values <code>x</code> are passed to a parameter of type <code>...E</code>
+and the respective <a href="#Passing_arguments_to_..._parameters">parameter
+passing rules</a> apply.
+As a special case, if the core type of <code>s</code> is <code>[]byte</code>,
+<code>append</code> also accepts a second argument with core type
+<a href="#Core_types"><code>bytestring</code></a> followed by <code>...</code>.
+This form appends the bytes of the byte slice or string.
+</p>
+
+<pre class="grammar">
+append(s S, x ...E) S  // core type of S is []E
+</pre>
+
+<p>
+If the capacity of <code>s</code> is not large enough to fit the additional
+values, <code>append</code> <a href="#Allocation">allocates</a> a new, sufficiently large underlying
+array that fits both the existing slice elements and the additional values.
+Otherwise, <code>append</code> re-uses the underlying array.
+</p>
+
+<pre>
+s0 := []int{0, 0}
+s1 := append(s0, 2)                // append a single element     s1 is []int{0, 0, 2}
+s2 := append(s1, 3, 5, 7)          // append multiple elements    s2 is []int{0, 0, 2, 3, 5, 7}
+s3 := append(s2, s0...)            // append a slice              s3 is []int{0, 0, 2, 3, 5, 7, 0, 0}
+s4 := append(s3[3:6], s3[2:]...)   // append overlapping slice    s4 is []int{3, 5, 7, 2, 3, 5, 7, 0, 0}
+
+var t []interface{}
+t = append(t, 42, 3.1415, "foo")   //                             t is []interface{}{42, 3.1415, "foo"}
+
+var b []byte
+b = append(b, "bar"...)            // append string contents      b is []byte{'b', 'a', 'r' }
+</pre>
+
+<p>
+The function <code>copy</code> copies slice elements from
+a source <code>src</code> to a destination <code>dst</code> and returns the
+number of elements copied.
+The <a href="#Core_types">core types</a> of both arguments must be slices
+with <a href="#Type_identity">identical</a> element type.
+The number of elements copied is the minimum of
+<code>len(src)</code> and <code>len(dst)</code>.
+As a special case, if the destination's core type is <code>[]byte</code>,
+<code>copy</code> also accepts a source argument with core type
+</a> <a href="#Core_types"><code>bytestring</code></a>.
+This form copies the bytes from the byte slice or string into the byte slice.
+</p>
+
+<pre class="grammar">
+copy(dst, src []T) int
+copy(dst []byte, src string) int
+</pre>
+
+<p>
+Examples:
+</p>
+
+<pre>
+var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
+var s = make([]int, 6)
+var b = make([]byte, 5)
+n1 := copy(s, a[0:])            // n1 == 6, s is []int{0, 1, 2, 3, 4, 5}
+n2 := copy(s, s[2:])            // n2 == 4, s is []int{2, 3, 4, 5, 4, 5}
+n3 := copy(b, "Hello, World!")  // n3 == 5, b is []byte("Hello")
+</pre>
+
+
+<h3 id="Clear">Clear</h3>
+
+<p>
+The built-in function <code>clear</code> takes an argument of <a href="#Map_types">map</a>,
+<a href="#Slice_types">slice</a>, or <a href="#Type_parameter_declarations">type parameter</a> type,
+and deletes or zeroes out all elements.
+</p>
+
+<pre class="grammar">
+Call        Argument type     Result
+
+clear(m)    map[K]T           deletes all entries, resulting in an
+                              empty map (len(m) == 0)
+
+clear(s)    []T               sets all elements up to the length of
+                              <code>s</code> to the zero value of T
+
+clear(t)    type parameter    see below
+</pre>
+
+<p>
+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>
+
+<p>
+If the map or slice is <code>nil</code>, <code>clear</code> is a no-op.
+</p>
+
+
 <h3 id="Close">Close</h3>
 
 <p>
@@ -7028,6 +7292,100 @@ The multi-valued <a href="#Receive_operator">receive operation</a>
 returns a received value along with an indication of whether the channel is closed.
 </p>
 
+
+<h3 id="Complex_numbers">Manipulating complex numbers</h3>
+
+<p>
+Three functions assemble and disassemble complex numbers.
+The built-in function <code>complex</code> constructs a complex
+value from a floating-point real and imaginary part, while
+<code>real</code> and <code>imag</code>
+extract the real and imaginary parts of a complex value.
+</p>
+
+<pre class="grammar">
+complex(realPart, imaginaryPart floatT) complexT
+real(complexT) floatT
+imag(complexT) floatT
+</pre>
+
+<p>
+The type of the arguments and return value correspond.
+For <code>complex</code>, the two arguments must be of the same
+<a href="#Numeric_types">floating-point type</a> and the return type is the
+<a href="#Numeric_types">complex type</a>
+with the corresponding floating-point constituents:
+<code>complex64</code> for <code>float32</code> arguments, and
+<code>complex128</code> for <code>float64</code> arguments.
+If one of the arguments evaluates to an untyped constant, it is first implicitly
+<a href="#Conversions">converted</a> to the type of the other argument.
+If both arguments evaluate to untyped constants, they must be non-complex
+numbers or their imaginary parts must be zero, and the return value of
+the function is an untyped complex constant.
+</p>
+
+<p>
+For <code>real</code> and <code>imag</code>, the argument must be
+of complex type, and the return type is the corresponding floating-point
+type: <code>float32</code> for a <code>complex64</code> argument, and
+<code>float64</code> for a <code>complex128</code> argument.
+If the argument evaluates to an untyped constant, it must be a number,
+and the return value of the function is an untyped floating-point constant.
+</p>
+
+<p>
+The <code>real</code> and <code>imag</code> functions together form the inverse of
+<code>complex</code>, so for a value <code>z</code> of a complex type <code>Z</code>,
+<code>z&nbsp;==&nbsp;Z(complex(real(z),&nbsp;imag(z)))</code>.
+</p>
+
+<p>
+If the operands of these functions are all constants, the return
+value is a constant.
+</p>
+
+<pre>
+var a = complex(2, -2)             // complex128
+const b = complex(1.0, -1.4)       // untyped complex constant 1 - 1.4i
+x := float32(math.Cos(math.Pi/2))  // float32
+var c64 = complex(5, -x)           // complex64
+var s int = complex(1, 0)          // untyped complex constant 1 + 0i can be converted to int
+_ = complex(1, 2&lt;&lt;s)               // illegal: 2 assumes floating-point type, cannot shift
+var rl = real(c64)                 // float32
+var im = imag(a)                   // float64
+const c = imag(b)                  // untyped constant -1.4
+_ = imag(3 &lt;&lt; s)                   // illegal: 3 assumes complex type, cannot shift
+</pre>
+
+<p>
+Arguments of type parameter type are not permitted.
+</p>
+
+
+<h3 id="Deletion_of_map_elements">Deletion of map elements</h3>
+
+<p>
+The built-in function <code>delete</code> removes the element with key
+<code>k</code> from a <a href="#Map_types">map</a> <code>m</code>. The
+value <code>k</code> must be <a href="#Assignability">assignable</a>
+to the key type of <code>m</code>.
+</p>
+
+<pre class="grammar">
+delete(m, k)  // remove element m[k] from map m
+</pre>
+
+<p>
+If the type of <code>m</code> is a <a href="#Type_parameter_declarations">type parameter</a>,
+all types in that type set must be maps, and they must all have identical key types.
+</p>
+
+<p>
+If the map <code>m</code> is <code>nil</code> or the element <code>m[k]</code>
+does not exist, <code>delete</code> is a no-op.
+</p>
+
+
 <h3 id="Length_and_capacity">Length and capacity</h3>
 
 <p>
@@ -7053,10 +7411,9 @@ cap(s)    [n]T, *[n]T      array length (== n)
 </pre>
 
 <p>
-If the argument type is a <a href="#Type_parameters">type parameter</a> <code>P</code>,
-<code>P</code> must have <a href="#Specific_types">specific types</a>, and
+If the argument type is a <a href="#Type_parameter_declarations">type parameter</a> <code>P</code>,
 the call <code>len(e)</code> (or <code>cap(e)</code> respectively) must be valid for
-each specific type of <code>P</code>.
+each type in <code>P</code>'s type set.
 The result is the length (or capacity, respectively) of the argument whose type
 corresponds to the type argument with which <code>P</code> was
 <a href="#Instantiations">instantiated</a>.
@@ -7099,36 +7456,6 @@ const (
 var z complex128
 </pre>
 
-<h3 id="Allocation">Allocation</h3>
-
-<p>
-The built-in function <code>new</code> takes a type <code>T</code>,
-allocates storage for a <a href="#Variables">variable</a> of that type
-at run time, and returns a value of type <code>*T</code>
-<a href="#Pointer_types">pointing</a> to it.
-The variable is initialized as described in the section on
-<a href="#The_zero_value">initial values</a>.
-</p>
-
-<pre class="grammar">
-new(T)
-</pre>
-
-<p>
-For instance
-</p>
-
-<pre>
-type S struct { a int; b float64 }
-new(S)
-</pre>
-
-<p>
-allocates storage for a variable of type <code>S</code>,
-initializes it (<code>a=0</code>, <code>b=0.0</code>),
-and returns a value of type <code>*S</code> containing the address
-of the location.
-</p>
 
 <h3 id="Making_slices_maps_and_channels">Making slices, maps and channels</h3>
 
@@ -7155,15 +7482,15 @@ make(T)          channel      unbuffered channel of type T
 make(T, n)       channel      buffered channel of type T, buffer size n
 </pre>
 
-
 <p>
-Each of the size arguments <code>n</code> and <code>m</code> must be of <a href="#Numeric_types">integer type</a>
-or an untyped <a href="#Constants">constant</a>.
+Each of the size arguments <code>n</code> and <code>m</code> must be of <a href="#Numeric_types">integer type</a>,
+have a <a href="#Interface_types">type set</a> containing only integer types,
+or be an untyped <a href="#Constants">constant</a>.
 A constant size argument must be non-negative and <a href="#Representability">representable</a>
 by a value of type <code>int</code>; if it is an untyped constant it is given type <code>int</code>.
 If both <code>n</code> and <code>m</code> are provided and are constant, then
 <code>n</code> must be no larger than <code>m</code>.
-If <code>n</code> is negative or larger than <code>m</code> at run time,
+For slices and channels, if <code>n</code> is negative or larger than <code>m</code> at run time,
 a <a href="#Run_time_panics">run-time panic</a> occurs.
 </p>
 
@@ -7183,176 +7510,101 @@ The precise behavior is implementation-dependent.
 </p>
 
 
-<h3 id="Appending_and_copying_slices">Appending to and copying slices</h3>
+<h3 id="Min_and_max">Min and max</h3>
 
 <p>
-The built-in functions <code>append</code> and <code>copy</code> assist in
-common slice operations.
-For both functions, the result is independent of whether the memory referenced
-by the arguments overlaps.
+The built-in functions <code>min</code> and <code>max</code> compute the
+smallest&mdash;or largest, respectively&mdash;value of a fixed number of
+arguments of <a href="#Comparison_operators">ordered types</a>.
+There must be at least one argument.
 </p>
 
 <p>
-The <a href="#Function_types">variadic</a> function <code>append</code>
-appends zero or more values <code>x</code> to a slice <code>s</code>
-and returns the resulting slice.
-The <a href="#Core_types">core type</a> of <code>s</code> must be a slice
-of the form <code>[]E</code>.
-The values <code>x</code> are passed to a parameter of type <code>...E</code>
-and the respective <a href="#Passing_arguments_to_..._parameters">parameter
-passing rules</a> apply.
-As a special case, if the core type of <code>s</code> is <code>[]byte</code>,
-<code>append</code> also accepts a second argument with core type <code>string</code>
-followed by <code>...</code>. This form appends the bytes of the string.
+The same type rules as for <a href="#Operators">operators</a> apply:
+for <a href="#Comparison_operators">ordered</a> arguments <code>x</code> and
+<code>y</code>, <code>min(x, y)</code> is valid if <code>x + y</code> is valid,
+and the type of <code>min(x, y)</code> is the type of <code>x + y</code>
+(and similarly for <code>max</code>).
+If all arguments are constant, the result is constant.
 </p>
 
-<pre class="grammar">
-append(s S, x ...E) S  // E is the element type of the core type of S
+<pre>
+var x, y int
+m := min(x)                 // m == x
+m := min(x, y)              // m is the smaller of x and y
+m := max(x, y, 10)          // m is the larger of x and y but at least 10
+c := max(1, 2.0, 10)        // c == 10.0 (floating-point kind)
+f := max(0, float32(x))     // type of f is float32
+var s []string
+_ = min(s...)               // invalid: slice arguments are not permitted
+t := max("", "foo", "bar")  // t == "foo" (string kind)
 </pre>
 
 <p>
-If the capacity of <code>s</code> is not large enough to fit the additional
-values, <code>append</code> allocates a new, sufficiently large underlying
-array that fits both the existing slice elements and the additional values.
-Otherwise, <code>append</code> re-uses the underlying array.
+For numeric arguments, assuming all NaNs are equal, <code>min</code> and <code>max</code> are
+commutative and associative:
 </p>
 
 <pre>
-s0 := []int{0, 0}
-s1 := append(s0, 2)                // append a single element     s1 == []int{0, 0, 2}
-s2 := append(s1, 3, 5, 7)          // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
-s3 := append(s2, s0...)            // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
-s4 := append(s3[3:6], s3[2:]...)   // append overlapping slice    s4 == []int{3, 5, 7, 2, 3, 5, 7, 0, 0}
-
-var t []interface{}
-t = append(t, 42, 3.1415, "foo")   //                             t == []interface{}{42, 3.1415, "foo"}
-
-var b []byte
-b = append(b, "bar"...)            // append string contents      b == []byte{'b', 'a', 'r' }
+min(x, y)    == min(y, x)
+min(x, y, z) == min(min(x, y), z) == min(x, min(y, z))
 </pre>
 
 <p>
-The function <code>copy</code> copies slice elements from
-a source <code>src</code> to a destination <code>dst</code> and returns the
-number of elements copied.
-The <a href="#Core_types">core types</a> of both arguments must be slices
-with <a href="#Type_identity">identical</a> element type.
-The number of elements copied is the minimum of
-<code>len(src)</code> and <code>len(dst)</code>.
-As a special case, if the destination's core type is <code>[]byte</code>,
-<code>copy</code> also accepts a source argument with core type <code>string</code>.
-This form copies the bytes from the string into the byte slice.
+For floating-point arguments negative zero, NaN, and infinity the following rules apply:
 </p>
 
-<pre class="grammar">
-copy(dst, src []T) int
-copy(dst []byte, src string) int
+<pre>
+   x        y    min(x, y)    max(x, y)
+
+  -0.0    0.0         -0.0          0.0    // negative zero is smaller than (non-negative) zero
+  -Inf      y         -Inf            y    // negative infinity is smaller than any other number
+  +Inf      y            y         +Inf    // positive infinity is larger than any other number
+   NaN      y          NaN          NaN    // if any argument is a NaN, the result is a NaN
 </pre>
 
 <p>
-Examples:
+For string arguments the result for <code>min</code> is the first argument
+with the smallest (or for <code>max</code>, largest) value,
+compared lexically byte-wise:
 </p>
 
 <pre>
-var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
-var s = make([]int, 6)
-var b = make([]byte, 5)
-n1 := copy(s, a[0:])            // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
-n2 := copy(s, s[2:])            // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
-n3 := copy(b, "Hello, World!")  // n3 == 5, b == []byte("Hello")
+min(x, y)    == if x <= y then x else y
+min(x, y, z) == min(min(x, y), z)
 </pre>
 
-
-<h3 id="Deletion_of_map_elements">Deletion of map elements</h3>
+<h3 id="Allocation">Allocation</h3>
 
 <p>
-The built-in function <code>delete</code> removes the element with key
-<code>k</code> from a <a href="#Map_types">map</a> <code>m</code>. The
-type of <code>k</code> must be <a href="#Assignability">assignable</a>
-to the key type of <code>m</code>.
+The built-in function <code>new</code> takes a type <code>T</code>,
+allocates storage for a <a href="#Variables">variable</a> of that type
+at run time, and returns a value of type <code>*T</code>
+<a href="#Pointer_types">pointing</a> to it.
+The variable is initialized as described in the section on
+<a href="#The_zero_value">initial values</a>.
 </p>
 
 <pre class="grammar">
-delete(m, k)  // remove element m[k] from map m
+new(T)
 </pre>
 
 <p>
-If the type of <code>m</code> is a <a href="#Type_parameters">type parameter</a>,
-it must have <a href="#Specific_types">specific types</a>, all specific types
-must be maps, and they must all have identical key types.
-</p>
-
-<p>
-If the map <code>m</code> is <code>nil</code> or the element <code>m[k]</code>
-does not exist, <code>delete</code> is a no-op.
-</p>
-
-
-<h3 id="Complex_numbers">Manipulating complex numbers</h3>
-
-<!-- We don't support generic arguments for these operations yet. -->
-
-<p>
-Three functions assemble and disassemble complex numbers.
-The built-in function <code>complex</code> constructs a complex
-value from a floating-point real and imaginary part, while
-<code>real</code> and <code>imag</code>
-extract the real and imaginary parts of a complex value.
+For instance
 </p>
 
-<pre class="grammar">
-complex(realPart, imaginaryPart floatT) complexT
-real(complexT) floatT
-imag(complexT) floatT
+<pre>
+type S struct { a int; b float64 }
+new(S)
 </pre>
 
 <p>
-The type of the arguments and return value correspond.
-For <code>complex</code>, the two arguments must be of the same
-<a href="#Numeric_types">floating-point type</a> and the return type is the
-<a href="#Numeric_types">complex type</a>
-with the corresponding floating-point constituents:
-<code>complex64</code> for <code>float32</code> arguments, and
-<code>complex128</code> for <code>float64</code> arguments.
-If one of the arguments evaluates to an untyped constant, it is first implicitly
-<a href="#Conversions">converted</a> to the type of the other argument.
-If both arguments evaluate to untyped constants, they must be non-complex
-numbers or their imaginary parts must be zero, and the return value of
-the function is an untyped complex constant.
-</p>
-
-<p>
-For <code>real</code> and <code>imag</code>, the argument must be
-of complex type, and the return type is the corresponding floating-point
-type: <code>float32</code> for a <code>complex64</code> argument, and
-<code>float64</code> for a <code>complex128</code> argument.
-If the argument evaluates to an untyped constant, it must be a number,
-and the return value of the function is an untyped floating-point constant.
-</p>
-
-<p>
-The <code>real</code> and <code>imag</code> functions together form the inverse of
-<code>complex</code>, so for a value <code>z</code> of a complex type <code>Z</code>,
-<code>z&nbsp;==&nbsp;Z(complex(real(z),&nbsp;imag(z)))</code>.
-</p>
-
-<p>
-If the operands of these functions are all constants, the return
-value is a constant.
+allocates storage for a variable of type <code>S</code>,
+initializes it (<code>a=0</code>, <code>b=0.0</code>),
+and returns a value of type <code>*S</code> containing the address
+of the location.
 </p>
 
-<pre>
-var a = complex(2, -2)             // complex128
-const b = complex(1.0, -1.4)       // untyped complex constant 1 - 1.4i
-x := float32(math.Cos(math.Pi/2))  // float32
-var c64 = complex(5, -x)           // complex64
-var s int = complex(1, 0)          // untyped complex constant 1 + 0i can be converted to int
-_ = complex(1, 2&lt;&lt;s)               // illegal: 2 assumes floating-point type, cannot shift
-var rl = real(c64)                 // float32
-var im = imag(a)                   // float64
-const c = imag(b)                  // untyped constant -1.4
-_ = imag(3 &lt;&lt; s)                   // illegal: 3 assumes complex type, cannot shift
-</pre>
 
 <h3 id="Handling_panics">Handling panics</h3>
 
@@ -7372,7 +7624,7 @@ an explicit call to <code>panic</code> or a <a href="#Run_time_panics">run-time
 terminates the execution of <code>F</code>.
 Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
 are then executed as usual.
-Next, any deferred functions run by <code>F's</code> caller are run,
+Next, any deferred functions run by <code>F</code>'s caller are run,
 and so on up to any deferred by the top-level function in the executing goroutine.
 At that point, the program is terminated and the error
 condition is reported, including the value of the argument to <code>panic</code>.
@@ -7402,19 +7654,13 @@ execution terminates by returning to its caller.
 </p>
 
 <p>
-The return value of <code>recover</code> is <code>nil</code> if any of the following conditions holds:
+The return value of <code>recover</code> is <code>nil</code> when the
+goroutine is not panicking or <code>recover</code> was not called directly by a deferred function.
+Conversely, if a goroutine is panicking and <code>recover</code> was called directly by a deferred function,
+the return value of <code>recover</code> is guaranteed not to be <code>nil</code>.
+To ensure this, calling <code>panic</code> with a <code>nil</code> interface value (or an untyped <code>nil</code>)
+causes a <a href="#Run_time_panics">run-time panic</a>.
 </p>
-<ul>
-<li>
-<code>panic</code>'s argument was <code>nil</code>;
-</li>
-<li>
-the goroutine is not panicking;
-</li>
-<li>
-<code>recover</code> was not called directly by a deferred function.
-</li>
-</ul>
 
 <p>
 The <code>protect</code> function in the example below invokes
@@ -7457,6 +7703,7 @@ accept arbitrary argument types, but printing of boolean, numeric, and string
 <a href="#Types">types</a> must be supported.
 </p>
 
+
 <h2 id="Packages">Packages</h2>
 
 <p>
@@ -7554,7 +7801,7 @@ and the Unicode replacement character U+FFFD.
 </p>
 
 <p>
-Assume we have compiled a package containing the package clause
+Consider a compiled a package containing the package clause
 <code>package math</code>, which exports function <code>Sin</code>, and
 installed the compiled package in the file identified by
 <code>"lib/math"</code>.
@@ -7730,6 +7977,9 @@ The declaration order of variables declared in multiple files is determined
 by the order in which the files are presented to the compiler: Variables
 declared in the first file are declared before any of the variables declared
 in the second file, and so on.
+To ensure reproducible initialization behavior, build systems are encouraged
+to present multiple files belonging to the same package in lexical file name
+order to a compiler.
 </p>
 
 <p>
@@ -7840,15 +8090,30 @@ in a program.
 </p>
 
 <p>
-A package with no imports is initialized by assigning initial values
-to all its package-level variables followed by calling all <code>init</code>
-functions in the order they appear in the source, possibly in multiple files,
-as presented to the compiler.
+The entire package is initialized by assigning initial values
+to all its package-level variables followed by calling
+all <code>init</code> functions in the order they appear
+in the source, possibly in multiple files, as presented
+to the compiler.
+</p>
+
+<h3 id="Program_initialization">Program initialization</h3>
+
+<p>
+The packages of a complete program are initialized stepwise, one package at a time.
 If a package has imports, the imported packages are initialized
 before initializing the package itself. If multiple packages import
 a package, the imported package will be initialized only once.
 The importing of packages, by construction, guarantees that there
 can be no cyclic initialization dependencies.
+More precisely:
+</p>
+
+<p>
+Given the list of all packages, sorted by import path, in each step the first
+uninitialized package in the list for which all imported packages (if any) are
+already initialized is <a href="#Package_initialization">initialized</a>.
+This step is repeated until all packages are initialized.
 </p>
 
 <p>
@@ -7862,13 +8127,6 @@ the <code>init</code> functions: it will not invoke the next one
 until the previous one has returned.
 </p>
 
-<p>
-To ensure reproducible initialization behavior, build systems are encouraged
-to present multiple files belonging to the same package in lexical file name
-order to a compiler.
-</p>
-
-
 <h3 id="Program_execution">Program execution</h3>
 <p>
 A complete program is created by linking a single, unimported package
@@ -7884,8 +8142,8 @@ func main() { … }
 </pre>
 
 <p>
-Program execution begins by initializing the main package and then
-invoking the function <code>main</code>.
+Program execution begins by <a href="#Program_initialization">initializing the program</a>
+and then invoking the function <code>main</code> in package <code>main</code>.
 When that function invocation returns, the program exits.
 It does not wait for other (non-<code>main</code>) goroutines to complete.
 </p>
@@ -7960,13 +8218,22 @@ func Sizeof(variable ArbitraryType) uintptr
 type IntegerType int  // shorthand for an integer type; it is not a real type
 func Add(ptr Pointer, len IntegerType) Pointer
 func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
+func SliceData(slice []ArbitraryType) *ArbitraryType
+func String(ptr *byte, len IntegerType) string
+func StringData(str string) *byte
 </pre>
 
+<!--
+These conversions also apply to type parameters with suitable core types.
+Determine if we can simply use core type instead of underlying type here,
+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 converted to
-a type of underlying type <code>Pointer</code> and vice versa.
+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>
 
@@ -8013,7 +8280,8 @@ uintptr(unsafe.Pointer(&amp;x)) % unsafe.Alignof(x) == 0
 
 <p>
 A (variable of) type <code>T</code> has <i>variable size</i> if <code>T</code>
-is a type parameter, or if it is an array or struct type containing elements
+is a <a href="#Type_parameter_declarations">type parameter</a>, or if it is an
+array or struct type containing elements
 or fields of variable size. Otherwise the size is <i>constant</i>.
 Calls to <code>Alignof</code>, <code>Offsetof</code>, and <code>Sizeof</code>
 are compile-time <a href="#Constant_expressions">constant expressions</a> of
@@ -8056,6 +8324,27 @@ or if <code>ptr</code> is <code>nil</code> and <code>len</code> is not zero,
 a <a href="#Run_time_panics">run-time panic</a> occurs.
 </p>
 
+<p>
+The function <code>SliceData</code> returns a pointer to the underlying array of the <code>slice</code> argument.
+If the slice's capacity <code>cap(slice)</code> is not zero, that pointer is <code>&slice[:1][0]</code>.
+If <code>slice</code> is <code>nil</code>, the result is <code>nil</code>.
+Otherwise it  is a non-<code>nil</code> pointer to an unspecified memory address.
+</p>
+
+<p>
+The function <code>String</code> returns a <code>string</code> value whose underlying bytes start at
+<code>ptr</code> and whose length is <code>len</code>.
+The same requirements apply to the <code>ptr</code> and <code>len</code> argument as in the function
+<code>Slice</code>. If <code>len</code> is zero, the result is the empty string <code>""</code>.
+Since Go strings are immutable, the bytes passed to <code>String</code> must not be modified afterwards.
+</p>
+
+<p>
+The function <code>StringData</code> returns a pointer to the underlying bytes of the <code>str</code> argument.
+For an empty string the return value is unspecified, and may be <code>nil</code>.
+Since Go strings are immutable, the bytes returned by <code>StringData</code> must not be modified.
+</p>
+
 <h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
 
 <p>
@@ -8091,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>