diff options
author | Robert Griesemer <gri@golang.org> | 2010-06-07 15:49:39 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2010-06-07 15:49:39 -0700 |
commit | bbbbbf8523f3e81ca82873254abdbb75d3a22e4f (patch) | |
tree | 87c059a878206ea84b59abdb67c5705871ba09fe /doc | |
parent | ded9ca954cd9b7380c814624137c02aaaf3516e6 (diff) | |
download | golang-bbbbbf8523f3e81ca82873254abdbb75d3a22e4f.tar.gz |
go spec: clean-up and consolidation of spec with implementation
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
http://codereview.appspot.com/1536041
Diffstat (limited to 'doc')
-rw-r--r-- | doc/go_spec.html | 243 |
1 files changed, 125 insertions, 118 deletions
diff --git a/doc/go_spec.html b/doc/go_spec.html index 5cd890ab9..dc9bd6497 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,5 +1,5 @@ <!-- title The Go Programming Language Specification --> -<!-- subtitle Version of June 1, 2010 --> +<!-- subtitle Version of June 7, 2010 --> <!-- TODO @@ -610,6 +610,27 @@ 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>). The method set of an <a href="#Interface_types">interface type</a> is its interface. @@ -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 (<-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> @@ -1359,18 +1366,6 @@ 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 = "+" | "-" | "!" | "^" | "*" | "&" | "<-" . <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>. |