]> Cypherpunks repositories - gostls13.git/commitdiff
go spec: clean-up and consolidation of spec with implementation
authorRobert Griesemer <gri@golang.org>
Mon, 7 Jun 2010 22:49:39 +0000 (15:49 -0700)
committerRobert Griesemer <gri@golang.org>
Mon, 7 Jun 2010 22:49:39 +0000 (15:49 -0700)
Specifically:
- introduced notion of "underlying type"
- removed notion of type compatibility
- consolidated rules about assignment compatibility in
  assignment compatibility section
- be consistent with specyfing that nil is the value
  for uninitialized variables that can be nil (this
  was not specified clearly for pointers, functions, interfaces)
- added/fixed various related links throughout
- clarify language on conversions

R=rsc, r, iant, ken2
CC=golang-dev
https://golang.org/cl/1536041

doc/go_spec.html

index 5cd890ab932ce3c967beccc30ae8626adb28c589..dc9bd64972308d1abea157418b0655be0acb033a 100644 (file)
@@ -1,5 +1,5 @@
 <!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of June 1, 2010 -->
+<!-- subtitle Version of June 7, 2010 -->
 
 <!--
 TODO
@@ -609,6 +609,27 @@ interface, slice, map, and channel types&mdash;may be constructed using
 type literals.
 </p>
 
+<p>
+Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
+is a predeclared type 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>.
+</p>
+
+<pre>
+   type T1 string
+   type T2 T1
+   type T3 []T1
+   type T4 T3
+</pre>
+
+<p>
+The underlying type of <code>string</code>, <code>T1</code>, and <code>T2</code>
+is <code>string</code>. The underlying type of <code>[]T1</code>, <code>T3</code>,
+and <code>T4</code> is <code>[]T1</code>.
+</p>
+
 <p>
 A type may have a <i>method set</i> associated with it
 (§<a href="#Interface_types">Interface types</a>, §<a href="#Method_declarations">Method declarations</a>).
@@ -626,7 +647,8 @@ The <i>static type</i> (or just <i>type</i>) of a variable is the
 type defined by its declaration.  Variables of interface type
 also have a distinct <i>dynamic type</i>, which
 is the actual type of the value stored in the variable at run-time.
-The dynamic type may vary during execution but is always assignment compatible
+The dynamic type may vary during execution but is always
+<a href="#Assignment_compatibility">assignment compatible</a>
 to the static type of the interface variable.  For non-interface
 types, the dynamic type is always the static type.
 </p>
@@ -687,7 +709,7 @@ uintptr  an unsigned integer large enough to store the uninterpreted bits of a p
 To avoid portability issues all numeric types are distinct except
 <code>byte</code>, which is an alias for <code>uint8</code>.
 Conversions
-are required when incompatible numeric types are mixed in an expression
+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.
@@ -753,7 +775,7 @@ multi-dimensional types.
 A slice is a reference to a contiguous segment of an array and
 contains a numbered sequence of elements from that array.  A slice
 type denotes the set of all slices of arrays of its element type.
-A slice value may be <code>nil</code>.
+The value of an uninitialized slice is <code>nil</code>.
 </p>
 
 <pre class="ebnf">
@@ -791,7 +813,6 @@ built-in function <code>cap(a)</code> and the relationship between
 </pre>
 
 <p>
-The value of an uninitialized slice is <code>nil</code>.
 The length and capacity of a <code>nil</code> slice
 are 0. A new, initialized slice value for a given element type <code>T</code> is
 made using the built-in function <code>make</code>, which takes a slice type
@@ -938,7 +959,7 @@ struct {
 <p>
 A pointer type denotes the set of all pointers to variables of a given
 type, called the <i>base type</i> of the pointer.
-A pointer value may be <code>nil</code>.
+The value of an unitialized pointer is <code>nil</code>.
 </p>
 
 <pre class="ebnf">
@@ -955,8 +976,8 @@ BaseType = Type .
 
 <p>
 A function type denotes the set of all functions with the same parameter
-and result types.
-A function value may be <code>nil</code>.
+and result types. The value of an unitialized variable of function type
+is <code>nil</code>.
 </p>
 
 <pre class="ebnf">
@@ -1006,7 +1027,8 @@ func(n int) func(p *T)
 An interface type specifies a <a href="#Types">method set</a> called its <i>interface</i>.
 A variable of interface type can store a value of any type with a method set
 that is any superset of the interface. Such a type is said to
-<i>implement the interface</i>. An interface value may be <code>nil</code>.
+<i>implement the interface</i>.
+The value of an unitialized variable of interface type is <code>nil</code>.
 </p>
 
 <pre class="ebnf">
@@ -1110,8 +1132,7 @@ type File interface {
 A map is an unordered group of elements of one type, called the
 element type, indexed by a set of unique <i>keys</i> of another type,
 called the key type.
-A map value may be <code>nil</code>.
-
+The value of an uninitialized map is <code>nil</code>.
 </p>
 
 <pre class="ebnf">
@@ -1143,7 +1164,6 @@ Values may be added and removed
 during execution using special forms of <a href="#Assignments">assignment</a>.
 </p>
 <p>
-The value of an uninitialized map is <code>nil</code>.
 A new, empty map value is made using the built-in
 function <code>make</code>, which takes the map type and an optional
 capacity hint as arguments:
@@ -1166,7 +1186,7 @@ stored in them.
 A channel provides a mechanism for two concurrently executing functions
 to synchronize execution and communicate by passing a value of a
 specified element type.
-A value of channel type may be <code>nil</code>.
+The value of an uninitialized channel is <code>nil</code>.
 </p>
 
 <pre class="ebnf">
@@ -1200,7 +1220,7 @@ chan (&lt;-chan int)
 </pre>
 
 <p>
-The value of an uninitialized channel is <code>nil</code>. A new, initialized channel
+A new, initialized channel
 value can be made using the built-in function
 <a href="#Making_slices_maps_and_channels"><code>make</code></a>,
 which takes the channel type and an optional capacity as arguments:
@@ -1224,21 +1244,17 @@ A channel may be closed and tested for closure with the built-in functions
 
 <h2 id="Properties_of_types_and_values">Properties of types and values</h2>
 
+<h3 id="Type_identity">Type identity</h3>
+
 <p>
-Two types are either <i>identical</i> or <i>different</i>, and they are
-either <i>compatible</i> or <i>incompatible</i>.
-Identical types are always compatible, but compatible types need not be identical.
+Two types are either <i>identical</i> or <i>different</i>.
 </p>
 
-<h3 id="Type_identity_and_compatibility">Type identity and compatibility</h3>
-
-<h4 id="Type_identity">Type identity</h4>
-
 <p>
 Two named types are identical if their type names originate in the same
-type declaration (§<a href="#Declarations_and_scope">Declarations and scope</a>).
+type <a href="#Declarations_and_scope">declaration</a>.
 A named and an unnamed type are always different. Two unnamed types are identical
-if the corresponding type literals are identical; that is if they have the same
+if the corresponding type literals are identical, that is, if they have the same
 literal structure and corresponding components have identical types. In detail:
 </p>
 
@@ -1272,14 +1288,6 @@ literal structure and corresponding components have identical types. In detail:
            the same direction.</li>
 </ul>
 
-<h4 id="Type_compatibility">Type compatibility</h4>
-
-<p>
-Type compatibility is less stringent than type identity: All identical types are
-compatible, but additionally a named and an unnamed type are compatible if the
-respective type literals are identical.
-</p>
-
 <p>
 Given the declarations
 </p>
@@ -1307,46 +1315,45 @@ func(x int, y float) *[]string and func(int, float) (result *[]string)
 </pre>
 
 <p>
-<code>T0</code> and <code>T1</code> are neither identical nor compatible
-because they are named types with distinct declarations.
-</p>
-
-<p>
-These types are compatible:
+<code>T0</code> and <code>T1</code> are different because they are named types
+with distinct declarations; <code>func(int, float) *T0</code> and
+<code>func(x int, y float) *[]string</code> are different because <code>T0</code>
+is different from <code>[]string</code>.
 </p>
 
-<pre>
-T0 and T0
-T0 and []string
-T3 and struct { a int; c int }
-T4 and func(x int, y float) (result *T0)
-</pre>
-
-<p>
-<code>T2</code> and <code>struct { a, c int }</code> are incompatible because
-they have different field names; <code>T4</code> and
-<code>func(x int, y float) *[]string</code> are incompatible because the
-respective type literals are different.
-</p>
 
 <h3 id="Assignment_compatibility">Assignment compatibility</h3>
 
 <p>
-A value <code>v</code> of static type <code>V</code> is <i>assignment compatible</i>
-with a type <code>T</code> if one or more of the following conditions applies:
+A value <code>x</code> is <i>assignment compatible</i> with type <code>T</code>
+(<code>x</code> <i>can be assigned to</i> <code>T</code>) in any of these cases:
 </p>
 
 <ul>
 <li>
-<code>V</code> is compatible with <code>T</code>.
+<code>x</code>'s type is identical to <code>T</code>.
+</li>
+<li>
+<code>x</code>'s type <code>V</code> or <code>T</code> have identical
+<a href="#Types">underlying types</a> and <code>V</code> or <code>T</code>
+is not a named type.
 </li>
 <li>
 <code>T</code> is an interface type and
-<code>V</code> <a href="#Interface_types">implements</a> <code>T</code>.
+<code>x</code> <a href="#Interface_types">implements</a> <code>T</code>.
+</li>
+<li>
+<code>x</code> is a bidirectional channel value, <code>T</code> is a channel type,
+<code>x</code>'s type <code>V</code> and <code>T</code> have identical element types,
+and <code>V</code> or <code>T</code> is not a named type.
 </li>
 <li>
-<code>V</code> is a bidirectional channel and <code>T</code> is a channel type
-with identical element type and at least one of <code>V</code> or <code>T</code> is unnamed.
+<code>x</code> is the predeclared identifier <code>nil</code> and <code>T</code>
+is a pointer, function, slice, map, channel, or interface type.
+</li>
+<li>
+<code>x</code> is an untyped <a href="#Constants">constant</a> representable
+by a value of type <code>T</code>.
 </li>
 </ul>
 
@@ -1358,18 +1365,6 @@ In other words, a struct value can be assigned to a struct variable only if
 every field of the struct may be legally assigned individually by the program.
 </p>
 
-<p>
-An untyped <a href="#Constants">constant</a> <code>v</code>
-is assignment compatible with type <code>T</code> if <code>v</code>
-can be represented accurately as a value of type <code>T</code>.
-</p>
-
-<p>
-The predeclared identifier <code>nil</code> is assignment compatible with any
-pointer, function, slice, map, channel, or interface type and
-represents the <a href="#The_zero_value">zero value</a> for that type.
-</p>
-
 <p>
 Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a>.
 </p>
@@ -1491,11 +1486,11 @@ The following identifiers are implicitly declared in the universe block:
 </p>
 <pre class="grammar">
 Basic types:
-       bool byte float32 float64 int8 int16 int32 int64
-       string uint8 uint16 uint32 uint64
+       bool byte complex64 complex128 float32 float64
+       int8 int16 int32 int64 string uint8 uint16 uint32 uint64
 
 Architecture-specific convenience types:
-       float int uint uintptr
+       complex float int uint uintptr
 
 Constants:
        true false iota
@@ -1659,10 +1654,9 @@ last non-empty expression list.
 
 <p>
 A type declaration binds an identifier, the <i>type name</i>, to a new type
-that has the same definition (element, fields, channel direction, etc.) as
-an existing type.  The new type is
-<a href="#Properties_of_types_and_values">compatible</a> with, but
-<a href="#Properties_of_types_and_values">different</a> from, the existing type.
+that has the same <a href="#Types">underlying type</a> as
+an existing type.  The new type is <a href="#Type_identity">different</a> from
+the existing type.
 </p>
 
 <pre class="ebnf">
@@ -2498,8 +2492,8 @@ The notation <code>x.(T)</code> is called a <i>type assertion</i>.
 </p>
 <p>
 More precisely, if <code>T</code> is not an interface type, <code>x.(T)</code> asserts
-that the dynamic type of <code>x</code> is identical to the type <code>T</code>
-(§<a href="#Type_identity">Type identity and compatibility</a>).
+that the dynamic type of <code>x</code> is <a href="#Type_identity">identical</a>
+to the 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> (§<a href="#Interface_types">Interface types</a>).
 </p>
@@ -2672,7 +2666,7 @@ Within <code>Greeting</code>, <code>who</code> will have value
 As a special case, if a function passes its own <code>...</code> parameter,
 with or without specified type, as the argument
 for a <code>...</code> in a call to another function with a <code>...</code> parameter
-of identical type,
+of <a href="#Type_identity">identical type</a>,
 the parameter is not wrapped again but passed directly. In short, a formal <code>...</code>
 parameter is passed unchanged as an actual <code>...</code> parameter provided the
 types match.
@@ -2700,8 +2694,7 @@ unary_op   = "+" | "-" | "!" | "^" | "*" | "&amp;" | "&lt;-" .
 
 <p>
 Comparisons are discussed <a href="#Comparison_operators">elsewhere</a>.
-For other binary operators, the operand types must be identical
-(§<a href="#Properties_of_types_and_values">Properties of types and values</a>)
+For other binary operators, the operand types must be <a href="#Type_identity">identical</a>
 unless the operation involves channels, shifts, or untyped <a href="#Constants">constants</a>.
 For operations involving constants only, see the section on
 <a href="#Constant_expressions">constant expressions</a>.
@@ -2924,8 +2917,8 @@ Comparison operators compare two operands and yield a value of type <code>bool</
 The operands must be <i>comparable</i>; that is, the first operand
 must be <a href="#Assignment_compatibility">assignment compatible</a>
 with the type of the second operand, or vice versa.
-<p>
 </p>
+<p>
 The operators <code>==</code> and <code>!=</code> apply
 to operands of all types except arrays and structs.
 All other comparison operators apply only to integer, floating-point
@@ -2969,7 +2962,7 @@ and string values. The result of a comparison is defined as follows:
        or if both are <code>nil</code>.
        </li>
        <li>
-       Interface values are equal if they have identical dynamic types and
+       Interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types and
        equal dynamic values or if both are <code>nil</code>.
        </li>
        <li>
@@ -3259,51 +3252,65 @@ If the type starts with an operator it must be parenthesized:
 </pre>
 
 <p>
-In general, a conversion is permitted if
-</p>
-<ol>
-<li>
-the value of <code>x</code> would be
-<a href="#Assignment_compatibility">assignment compatible</a> with type
-<code>T</code> if <code>T</code> were unnamed
-</li>
-<li>
-<code>x</code> is of an unnamed pointer type and type <code>T</code> is another
-unnamed pointer type and the previous rule applies to the pointer base types.
-</li>
-</ol>
-<p>
-Such a conversion changes the type but not the representation of <code>x</code>.
+A value <code>x</code> can be converted to type <code>T</code> in any
+of these cases:
 </p>
 
-<p>
-Specific rules apply to conversions where <code>T</code> is a
-numeric or string type, or where <code>x</code> is of string type.
-These conversions may change the representation of a value and incur a run-time cost.
-</p>
+<ul>
+       <li>
+       <code>x</code> can be <a href="#Assignment_compatibility">assigned</a>
+       to <code>T</code>.
+       </li>
+       <li>
+       <code>x</code>'s type and <code>T</code> have identical
+       <a href="#Types">underlying types</a>.
+       </li>
+       <li>
+       <code>x</code>'s type and <code>T</code> are unnamed pointer types
+       and their pointer base types have identical underlying types.
+       </li>
+       <li>
+       <code>x</code>'s type and <code>T</code> are both integer or floating
+       point types.
+       </li>
+       <li>
+       <code>x</code>'s type and <code>T</code> are both complex types.
+       </li>
+       <li>
+       <code>x</code> is an integer or has type <code>[]byte</code> or
+       <code>[]int</code> and <code>T</code> is a string type.
+       </li>
+       <li>
+       <code>x</code> is a string and <code>T</code> is <code>[]byte</code> or
+       <code>[]int</code>.
+       </li>
+</ul>
 
-<h4>Conversions between integer types</h4>
 <p>
-If the value is a signed quantity, it is
-sign extended to implicit infinite precision; otherwise it is zero
-extended.  It is then truncated to fit in the result type's size.
-For example, if <code>x := uint16(0x10F0)</code>, then <code>uint32(int8(x)) == 0xFFFFFFF0</code>.
-The conversion always yields a valid value; there is no indication of overflow.
+Specific rules apply to conversions between numeric types or to and from
+a string type.
+These conversions may change the representation of <code>x</code>
+and incur a run-time cost.
+All other conversions only change the type but not the representation
+of <code>x</code>.
 </p>
 
-<h4>Conversions involving floating point and complex types</h4>
+<h4>Conversions between numeric types</h4>
 <ol>
 <li>
-When converting a floating-point number to an integer, the fraction is discarded
-(truncation towards zero).
+When converting between integer types, if the value is a signed integer, it is
+sign extended to implicit infinite precision; otherwise it is zero extended.
+It is then truncated to fit in the result type's size.
+For example, if <code>v := uint16(0x10F0)</code>, then <code>uint32(int8(v)) == 0xFFFFFFF0</code>.
+The conversion always yields a valid value; there is no indication of overflow.
 </li>
 <li>
-A value of complex type may be converted to a different complex type,
-but there is no conversion between complex and any other type.
+When converting a floating-point number to an integer, the fraction is discarded
+(truncation towards zero).
 </li>
 <li>
-When converting a number to a floating-point or complex type,
-the result value is rounded
+When converting an integer or floating-point number to a floating-point type,
+or a complex number to another complex type, the result value is rounded
 to the precision specified by the destination type.
 For instance, the value of a variable <code>x</code> of type <code>float32</code>
 may be stored using additional precision beyond that of an IEEE-754 32-bit number,
@@ -3325,8 +3332,8 @@ implementation-dependent.
 <ol>
 <li>
 Converting a signed or unsigned integer value to a string type yields a
-string containing the UTF-8 representation of the integer.
-Negative values are converted to <code>"\uFFFD"</code>.
+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"
@@ -4486,7 +4493,7 @@ m := make(map[string] int, 100)  // map with initial space for 100 elements
 The built-in 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. Source and destination may overlap.
-Both arguments must have identical element type <code>T</code> and must be
+Both arguments must have <a href="#Type_identity">identical</a> element type <code>T</code> and must be
 <a href="#Assignment_compatibility">assignment compatible</a> to a slice
 of type <code>[]T</code>. The number of arguments copied is the minimum of
 <code>len(src)</code> and <code>len(dst)</code>.