mirror of
https://github.com/golang/go
synced 2024-11-21 20:54:45 -07:00
go spec: change def. of "type compatibility" to be non-recursive
and adjust conversion rules. Also: - clarification of type identity (no language change) - adjust special rules for channel assignment/comparison to require identical element types (in correspondence to non- recursiveness of type compatibility) R=rsc, iant, ken2, r CC=golang-dev https://golang.org/cl/1376042
This commit is contained in:
parent
2bb59fd71a
commit
63f014910d
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Todo
|
Todo
|
||||||
[ ] clarify: two equal lowercase identifiers from different packages denote different objects
|
[ ] clarify: two equal lower-case identifiers from different packages denote different objects
|
||||||
[ ] need language about function/method calls and parameter passing rules
|
[ ] need language about function/method calls and parameter passing rules
|
||||||
[ ] last paragraph of #Assignments (constant promotion) should be elsewhere
|
[ ] last paragraph of #Assignments (constant promotion) should be elsewhere
|
||||||
and mention assignment to empty interface.
|
and mention assignment to empty interface.
|
||||||
@ -1236,10 +1236,10 @@ Identical types are always compatible, but compatible types need not be identica
|
|||||||
|
|
||||||
<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>). A named and an unnamed type
|
type declaration (§<a href="#Declarations_and_scope">Declarations and scope</a>).
|
||||||
are never identical. Two unnamed types are identical if the corresponding
|
A named and an unnamed type are always different. Two unnamed types are identical
|
||||||
type literals have the same literal structure and corresponding components have
|
if the corresponding type literals are identical; that is if they have the same
|
||||||
identical types. In detail:
|
literal structure and corresponding components have identical types. In detail:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@ -1250,7 +1250,8 @@ identical types. In detail:
|
|||||||
|
|
||||||
<li>Two struct types are identical if they have the same sequence of fields,
|
<li>Two struct types are identical if they have the same sequence of fields,
|
||||||
and if corresponding fields have the same names and identical types.
|
and if corresponding fields have the same names and identical types.
|
||||||
Two anonymous fields are considered to have the same name.</li>
|
Two anonymous fields are considered to have the same name. Lower-case field
|
||||||
|
names from different packages are always different.</li>
|
||||||
|
|
||||||
<li>Two pointer types are identical if they have identical base types.</li>
|
<li>Two pointer types are identical if they have identical base types.</li>
|
||||||
|
|
||||||
@ -1262,8 +1263,8 @@ identical types. In detail:
|
|||||||
Parameter and result names are not required to match.</li>
|
Parameter and result names are not required to match.</li>
|
||||||
|
|
||||||
<li>Two interface types are identical if they have the same set of methods
|
<li>Two interface types are identical if they have the same set of methods
|
||||||
with the same names and identical function types. The order
|
with the same names and identical function types. Lower-case method names from
|
||||||
of the methods is irrelevant.</li>
|
different packages are always different. The order of the methods is irrelevant.</li>
|
||||||
|
|
||||||
<li>Two map types are identical if they have identical key and value types.</li>
|
<li>Two map types are identical if they have identical key and value types.</li>
|
||||||
|
|
||||||
@ -1274,11 +1275,9 @@ identical types. In detail:
|
|||||||
<h4 id="Type_compatibility">Type compatibility</h4>
|
<h4 id="Type_compatibility">Type compatibility</h4>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Type compatibility is less stringent than type identity: a named and an unnamed
|
Type compatibility is less stringent than type identity: All identical types are
|
||||||
type are compatible if the respective type literals are compatible.
|
compatible, but additionally a named and an unnamed type are compatible if the
|
||||||
In all other respects, the definition of type compatibility is the
|
respective type literals are identical.
|
||||||
same as for type identity listed above but with ``compatible''
|
|
||||||
substituted for ``identical''.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -1320,12 +1319,14 @@ These types are compatible:
|
|||||||
T0 and T0
|
T0 and T0
|
||||||
T0 and []string
|
T0 and []string
|
||||||
T3 and struct { a int; c int }
|
T3 and struct { a int; c int }
|
||||||
T4 and func(x int, y float) *[]string
|
T4 and func(x int, y float) (result *T0)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<code>T2</code> and <code>struct { a, c int }</code> are incompatible because
|
<code>T2</code> and <code>struct { a, c int }</code> are incompatible because
|
||||||
they have different field names.
|
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>
|
</p>
|
||||||
|
|
||||||
<h3 id="Assignment_compatibility">Assignment compatibility</h3>
|
<h3 id="Assignment_compatibility">Assignment compatibility</h3>
|
||||||
@ -1345,7 +1346,7 @@ with a type <code>T</code> if one or more of the following conditions applies:
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<code>V</code> is a bidirectional channel and <code>T</code> is a channel type
|
<code>V</code> is a bidirectional channel and <code>T</code> is a channel type
|
||||||
with compatible element type and at least one of <code>V</code> or <code>T</code> is unnamed.
|
with identical element type and at least one of <code>V</code> or <code>T</code> is unnamed.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -1418,7 +1419,7 @@ Function values are equal if they refer to the same function.
|
|||||||
Channel and map values are equal if they were created by the same call to <code>make</code>
|
Channel and map values are equal if they were created by the same call to <code>make</code>
|
||||||
(§<a href="#Making_slices">Making slices</a>, maps, and channels).
|
(§<a href="#Making_slices">Making slices</a>, maps, and channels).
|
||||||
When comparing two values of channel type, the channel value types
|
When comparing two values of channel type, the channel value types
|
||||||
must be compatible but the channel direction is ignored.
|
must be identical but the channel direction is ignored.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Interface values may be compared if they have compatible static types.
|
Interface values may be compared if they have compatible static types.
|
||||||
@ -2550,7 +2551,7 @@ 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
|
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 identical to the type <code>T</code>
|
||||||
(§<a href="#Type_identity_and_compatibility">Type identity and compatibility</a>).
|
(§<a href="#Type_identity">Type identity and compatibility</a>).
|
||||||
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>
|
||||||
@ -2642,7 +2643,7 @@ if Join(Split(value, len(value)/2)) != value {
|
|||||||
<p>
|
<p>
|
||||||
A method call <code>x.m()</code> is valid if the method set of
|
A method call <code>x.m()</code> is valid if the method set of
|
||||||
(the type of) <code>x</code> contains <code>m</code> and the
|
(the type of) <code>x</code> contains <code>m</code> and the
|
||||||
argument list is compatible with the parameter list of <code>m</code>.
|
argument list can be assigned to the parameter list of <code>m</code>.
|
||||||
If <code>x</code> is <a href="#Address_operators">addressable</a> and <code>&x</code>'s method
|
If <code>x</code> is <a href="#Address_operators">addressable</a> and <code>&x</code>'s method
|
||||||
set contains <code>m</code>, <code>x.m()</code> is shorthand
|
set contains <code>m</code>, <code>x.m()</code> is shorthand
|
||||||
for <code>(&x).m()</code>:
|
for <code>(&x).m()</code>:
|
||||||
@ -3263,12 +3264,21 @@ If the type starts with an operator it must be parenthesized:
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In general, a conversion succeeds if the value of <code>x</code> is
|
In general, a conversion is permitted if
|
||||||
<a href="#Assignment_compatibility">assignment compatible</a> with type <code>T</code>,
|
</p>
|
||||||
or if the value would be assignment compatible with type <code>T</code> if the
|
<ol>
|
||||||
value's type, or <code>T</code>, or any of their component types were unnamed.
|
<li>
|
||||||
Usually, such a conversion changes the type but not the representation of the value
|
the value of <code>x</code> would be
|
||||||
of <code>x</code> and thus has no run-time cost.
|
<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>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -4478,10 +4488,10 @@ m := make(map[string] int, 100) // map with initial space for 100 elements
|
|||||||
<h3 id="Copying_slices">Copying slices</h3>
|
<h3 id="Copying_slices">Copying slices</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The built-in function <code>copy</code> copies array or 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 the same element type <code>T</code> and must be
|
Both arguments must have identical 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>.
|
||||||
@ -4498,7 +4508,7 @@ Examples:
|
|||||||
<pre>
|
<pre>
|
||||||
var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
|
var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
|
||||||
var s = make([]int, 6)
|
var s = make([]int, 6)
|
||||||
n1 := copy(s, &a) // n1 == 6, s == []int{0, 1, 2, 3, 4, 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}
|
n2 := copy(s, s[2:]) // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user