1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:04:41 -07:00

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 --> <!-- title The Go Programming Language Specification -->
<!-- subtitle Version of June 1, 2010 --> <!-- subtitle Version of June 7, 2010 -->
<!-- <!--
TODO TODO
@ -609,6 +609,27 @@ interface, slice, map, and channel types&mdash;may be constructed using
type literals. type literals.
</p> </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> <p>
A type may have a <i>method set</i> associated with it 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>). <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 type defined by its declaration. Variables of interface type
also have a distinct <i>dynamic type</i>, which also have a distinct <i>dynamic type</i>, which
is the actual type of the value stored in the variable at run-time. 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 to the static type of the interface variable. For non-interface
types, the dynamic type is always the static type. types, the dynamic type is always the static type.
</p> </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 To avoid portability issues all numeric types are distinct except
<code>byte</code>, which is an alias for <code>uint8</code>. <code>byte</code>, which is an alias for <code>uint8</code>.
Conversions 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> 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 are not the same type even though they may have the same size on a
particular architecture. particular architecture.
@ -753,7 +775,7 @@ multi-dimensional types.
A slice is a reference to a contiguous segment of an array and A slice is a reference to a contiguous segment of an array and
contains a numbered sequence of elements from that array. A slice contains a numbered sequence of elements from that array. A slice
type denotes the set of all slices of arrays of its element type. 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> </p>
<pre class="ebnf"> <pre class="ebnf">
@ -791,7 +813,6 @@ built-in function <code>cap(a)</code> and the relationship between
</pre> </pre>
<p> <p>
The value of an uninitialized slice is <code>nil</code>.
The length and capacity of a <code>nil</code> slice 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 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 made using the built-in function <code>make</code>, which takes a slice type
@ -938,7 +959,7 @@ struct {
<p> <p>
A pointer type denotes the set of all pointers to variables of a given A pointer type denotes the set of all pointers to variables of a given
type, called the <i>base type</i> of the pointer. 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> </p>
<pre class="ebnf"> <pre class="ebnf">
@ -955,8 +976,8 @@ BaseType = Type .
<p> <p>
A function type denotes the set of all functions with the same parameter A function type denotes the set of all functions with the same parameter
and result types. and result types. The value of an unitialized variable of function type
A function value may be <code>nil</code>. is <code>nil</code>.
</p> </p>
<pre class="ebnf"> <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>. 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 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 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> </p>
<pre class="ebnf"> <pre class="ebnf">
@ -1110,8 +1132,7 @@ type File interface {
A map is an unordered group of elements of one type, called the 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, element type, indexed by a set of unique <i>keys</i> of another type,
called the key type. called the key type.
A map value may be <code>nil</code>. The value of an uninitialized map is <code>nil</code>.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
@ -1143,7 +1164,6 @@ Values may be added and removed
during execution using special forms of <a href="#Assignments">assignment</a>. during execution using special forms of <a href="#Assignments">assignment</a>.
</p> </p>
<p> <p>
The value of an uninitialized map is <code>nil</code>.
A new, empty map value is made using the built-in A new, empty map value is made using the built-in
function <code>make</code>, which takes the map type and an optional function <code>make</code>, which takes the map type and an optional
capacity hint as arguments: capacity hint as arguments:
@ -1166,7 +1186,7 @@ stored in them.
A channel provides a mechanism for two concurrently executing functions A channel provides a mechanism for two concurrently executing functions
to synchronize execution and communicate by passing a value of a to synchronize execution and communicate by passing a value of a
specified element type. specified element type.
A value of channel type may be <code>nil</code>. The value of an uninitialized channel is <code>nil</code>.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
@ -1200,7 +1220,7 @@ chan (&lt;-chan int)
</pre> </pre>
<p> <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 value can be made using the built-in function
<a href="#Making_slices_maps_and_channels"><code>make</code></a>, <a href="#Making_slices_maps_and_channels"><code>make</code></a>,
which takes the channel type and an optional capacity as arguments: 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> <h2 id="Properties_of_types_and_values">Properties of types and values</h2>
<h3 id="Type_identity">Type identity</h3>
<p> <p>
Two types are either <i>identical</i> or <i>different</i>, and they are Two types are either <i>identical</i> or <i>different</i>.
either <i>compatible</i> or <i>incompatible</i>.
Identical types are always compatible, but compatible types need not be identical.
</p> </p>
<h3 id="Type_identity_and_compatibility">Type identity and compatibility</h3>
<h4 id="Type_identity">Type identity</h4>
<p> <p>
Two named types are identical if their type names originate in the same 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 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: literal structure and corresponding components have identical types. In detail:
</p> </p>
@ -1272,14 +1288,6 @@ literal structure and corresponding components have identical types. In detail:
the same direction.</li> the same direction.</li>
</ul> </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> <p>
Given the declarations Given the declarations
</p> </p>
@ -1307,46 +1315,45 @@ func(x int, y float) *[]string and func(int, float) (result *[]string)
</pre> </pre>
<p> <p>
<code>T0</code> and <code>T1</code> are neither identical nor compatible <code>T0</code> and <code>T1</code> are different because they are named types
because they are named types with distinct declarations. 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>
<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> <h3 id="Assignment_compatibility">Assignment compatibility</h3>
<p> <p>
A value <code>v</code> of static type <code>V</code> is <i>assignment compatible</i> A value <code>x</code> is <i>assignment compatible</i> with type <code>T</code>
with a type <code>T</code> if one or more of the following conditions applies: (<code>x</code> <i>can be assigned to</i> <code>T</code>) in any of these cases:
</p> </p>
<ul> <ul>
<li> <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>
<li> <li>
<code>T</code> is an interface type and <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>
<li> <li>
<code>V</code> is a bidirectional channel and <code>T</code> is a channel type <code>x</code> is a bidirectional channel value, <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>'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> </li>
</ul> </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. every field of the struct may be legally assigned individually by the program.
</p> </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> <p>
Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a>. Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a>.
</p> </p>
@ -1491,11 +1486,11 @@ The following identifiers are implicitly declared in the universe block:
</p> </p>
<pre class="grammar"> <pre class="grammar">
Basic types: Basic types:
bool byte float32 float64 int8 int16 int32 int64 bool byte complex64 complex128 float32 float64
string uint8 uint16 uint32 uint64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64
Architecture-specific convenience types: Architecture-specific convenience types:
float int uint uintptr complex float int uint uintptr
Constants: Constants:
true false iota true false iota
@ -1659,10 +1654,9 @@ last non-empty expression list.
<p> <p>
A type declaration binds an identifier, the <i>type name</i>, to a new type 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 that has the same <a href="#Types">underlying type</a> as
an existing type. The new type is an existing type. The new type is <a href="#Type_identity">different</a> from
<a href="#Properties_of_types_and_values">compatible</a> with, but the existing type.
<a href="#Properties_of_types_and_values">different</a> from, the existing type.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
@ -2498,8 +2492,8 @@ The notation <code>x.(T)</code> is called a <i>type assertion</i>.
</p> </p>
<p> <p>
More precisely, if <code>T</code> is not an interface type, <code>x.(T)</code> asserts 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> that the dynamic type of <code>x</code> is <a href="#Type_identity">identical</a>
<a href="#Type_identity">Type identity and compatibility</a>). to the type <code>T</code>.
If <code>T</code> is an interface type, <code>x.(T)</code> asserts that the dynamic type 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>). of <code>x</code> implements the interface <code>T</code><a href="#Interface_types">Interface types</a>).
</p> </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, As a special case, if a function passes its own <code>...</code> parameter,
with or without specified type, as the argument with or without specified type, as the argument
for a <code>...</code> in a call to another function with a <code>...</code> parameter 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> 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 parameter is passed unchanged as an actual <code>...</code> parameter provided the
types match. types match.
@ -2700,8 +2694,7 @@ unary_op = "+" | "-" | "!" | "^" | "*" | "&amp;" | "&lt;-" .
<p> <p>
Comparisons are discussed <a href="#Comparison_operators">elsewhere</a>. Comparisons are discussed <a href="#Comparison_operators">elsewhere</a>.
For other binary operators, the operand types must be identical For other binary operators, the operand types must be <a href="#Type_identity">identical</a>
<a href="#Properties_of_types_and_values">Properties of types and values</a>)
unless the operation involves channels, shifts, or untyped <a href="#Constants">constants</a>. unless the operation involves channels, shifts, or untyped <a href="#Constants">constants</a>.
For operations involving constants only, see the section on For operations involving constants only, see the section on
<a href="#Constant_expressions">constant expressions</a>. <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 The operands must be <i>comparable</i>; that is, the first operand
must be <a href="#Assignment_compatibility">assignment compatible</a> must be <a href="#Assignment_compatibility">assignment compatible</a>
with the type of the second operand, or vice versa. with the type of the second operand, or vice versa.
<p>
</p> </p>
<p>
The operators <code>==</code> and <code>!=</code> apply The operators <code>==</code> and <code>!=</code> apply
to operands of all types except arrays and structs. to operands of all types except arrays and structs.
All other comparison operators apply only to integer, floating-point 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>. or if both are <code>nil</code>.
</li> </li>
<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>. equal dynamic values or if both are <code>nil</code>.
</li> </li>
<li> <li>
@ -3259,51 +3252,65 @@ If the type starts with an operator it must be parenthesized:
</pre> </pre>
<p> <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> </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> <ol>
<li> <li>
the value of <code>x</code> would be When converting between integer types, if the value is a signed integer, it is
<a href="#Assignment_compatibility">assignment compatible</a> with type sign extended to implicit infinite precision; otherwise it is zero extended.
<code>T</code> if <code>T</code> were unnamed It is then truncated to fit in the result type's size.
</li> For example, if <code>v := uint16(0x10F0)</code>, then <code>uint32(int8(v)) == 0xFFFFFFF0</code>.
<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>.
The conversion always yields a valid value; there is no indication of overflow. The conversion always yields a valid value; there is no indication of overflow.
</p> </li>
<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 When converting a floating-point number to an integer, the fraction is discarded
(truncation towards zero). (truncation towards zero).
</li> </li>
<li> <li>
A value of complex type may be converted to a different complex type, When converting an integer or floating-point number to a floating-point type,
but there is no conversion between complex and any other type. or a complex number to another complex type, the result value is rounded
</li>
<li>
When converting a number to a floating-point or complex type,
the result value is rounded
to the precision specified by the destination type. to the precision specified by the destination type.
For instance, the value of a variable <code>x</code> of type <code>float32</code> 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, may be stored using additional precision beyond that of an IEEE-754 32-bit number,
@ -3325,8 +3332,8 @@ implementation-dependent.
<ol> <ol>
<li> <li>
Converting a signed or unsigned integer value to a string type yields a Converting a signed or unsigned integer value to a string type yields a
string containing the UTF-8 representation of the integer. string containing the UTF-8 representation of the integer. Values outside
Negative values are converted to <code>"\uFFFD"</code>. the range of valid Unicode code points are converted to <code>"\uFFFD"</code>.
<pre> <pre>
string('a') // "a" 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 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 a source <code>src</code> to a destination <code>dst</code> and returns the
number of elements copied. Source and destination may overlap. 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 <a href="#Assignment_compatibility">assignment compatible</a> to a slice
of type <code>[]T</code>. The number of arguments copied is the minimum of of type <code>[]T</code>. The number of arguments copied is the minimum of
<code>len(src)</code> and <code>len(dst)</code>. <code>len(src)</code> and <code>len(dst)</code>.