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
https://golang.org/cl/1536041
This commit is contained in:
Robert Griesemer 2010-06-07 15:49:39 -07:00
parent 129c6c14d1
commit 7bc03718f4

View 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.
<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>
<p>
These types are compatible:
</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>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 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>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
A value <code>x</code> can be converted to type <code>T</code> in any
of these cases:
</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>
<p>
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 between numeric types</h4>
<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>.
</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>
<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>.
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.
</p>
<h4>Conversions involving floating point and complex types</h4>
<ol>
</li>
<li>
When converting a floating-point number to an integer, the fraction is discarded
(truncation towards zero).
</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.
</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>.