mirror of
https://github.com/golang/go
synced 2024-11-11 22:50:22 -07:00
spec: introduce notion of strict comparability
- Rephrase the notion of "comparability" from a property of values (operands) to a property of types and adjust dependent prose. - Introduce the notion of "strict comparability". - Fix the definitions of comparability for type interfaces and type parameters. - Define the predeclared identifier "comparable" as stricly comparable. These changes address existing problems in the spec as outlined in the section on "Related spec issues" in issue #56548. For #56548. Change-Id: Ibc8c2f36d92857a5134eadc18358624803d3dd21 Reviewed-on: https://go-review.googlesource.com/c/go/+/457095 Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Bypass: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
cb07765045
commit
ffefcd360b
@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of November 21, 2022",
|
||||
"Subtitle": "Version of December 14, 2022",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@ -2684,18 +2684,17 @@ other interfaces based on their type sets. But this should get us going for now.
|
||||
The <a href="#Predeclared_identifiers">predeclared</a>
|
||||
<a href="#Interface_types">interface type</a> <code>comparable</code>
|
||||
denotes the set of all non-interface types that are
|
||||
<a href="#Comparison_operators">comparable</a>. Specifically,
|
||||
<a href="#Comparison_operators">strictly comparable</a>. Specifically,
|
||||
a type <code>T</code> implements <code>comparable</code> if:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>T</code> is not an interface type and <code>T</code> supports the operations
|
||||
<code>==</code> and <code>!=</code>; or
|
||||
<code>T</code> is not an interface type and <code>T</code> is strictly comparable; or
|
||||
</li>
|
||||
<li>
|
||||
<code>T</code> is an interface type and each type in <code>T</code>'s
|
||||
<a href="#Interface_types">type set</a> implements <code>comparable</code>.
|
||||
<a href="#Interface_types">type set</a> is strictly comparable.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -2707,12 +2706,13 @@ Even though interfaces that are not type parameters can be
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int // implements comparable
|
||||
int // implements comparable (int is strictly comparable)
|
||||
[]byte // does not implement comparable (slices cannot be compared)
|
||||
interface{} // does not implement comparable (see above)
|
||||
interface{ ~int | ~string } // type parameter only: implements comparable
|
||||
interface{ comparable } // type parameter only: implements comparable
|
||||
interface{ ~int | ~[]byte } // type parameter only: does not implement comparable (not all types in the type set are comparable)
|
||||
interface{ ~int | ~string } // type parameter only: implements comparable (int, string types are stricly comparable)
|
||||
interface{ comparable } // type parameter only: implements comparable (comparable implements itself)
|
||||
interface{ ~int | ~[]byte } // type parameter only: does not implement comparable (slices are not comparable)
|
||||
interface{ ~struct{ any } } // type parameter only: does not implement comparable (field any is not strictly comparable)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@ -5019,69 +5019,71 @@ to the type of the second operand, or vice versa.
|
||||
</p>
|
||||
<p>
|
||||
The equality operators <code>==</code> and <code>!=</code> apply
|
||||
to operands that are <i>comparable</i>.
|
||||
to operands of <i>comparable</i> types.
|
||||
The ordering operators <code><</code>, <code><=</code>, <code>></code>, and <code>>=</code>
|
||||
apply to operands that are <i>ordered</i>.
|
||||
apply to operands of <i>ordered</i> types.
|
||||
These terms and the result of the comparisons are defined as follows:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Boolean values are comparable.
|
||||
Boolean types are comparable.
|
||||
Two boolean values are equal if they are either both
|
||||
<code>true</code> or both <code>false</code>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Integer values are comparable and ordered, in the usual way.
|
||||
Integer types are comparable and ordered.
|
||||
Two integer values are compared in the usual way.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Floating-point values are comparable and ordered,
|
||||
as defined by the IEEE-754 standard.
|
||||
Floating-point types are comparable and ordered.
|
||||
Two floating-point values are compared as defined by the IEEE-754 standard.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Complex values are comparable.
|
||||
Complex types are comparable.
|
||||
Two complex values <code>u</code> and <code>v</code> are
|
||||
equal if both <code>real(u) == real(v)</code> and
|
||||
<code>imag(u) == imag(v)</code>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
String values are comparable and ordered, lexically byte-wise.
|
||||
String types are comparable and ordered.
|
||||
Two string values are compared lexically byte-wise.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Pointer values are comparable.
|
||||
Pointer types are comparable.
|
||||
Two pointer values are equal if they point to the same variable or if both have value <code>nil</code>.
|
||||
Pointers to distinct <a href="#Size_and_alignment_guarantees">zero-size</a> variables may or may not be equal.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Channel values are comparable.
|
||||
Channel types are comparable.
|
||||
Two channel values are equal if they were created by the same call to
|
||||
<a href="#Making_slices_maps_and_channels"><code>make</code></a>
|
||||
or if both have value <code>nil</code>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Interface values are comparable.
|
||||
Interface types that are not type parameters are comparable.
|
||||
Two interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types
|
||||
and equal dynamic values or if both have value <code>nil</code>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
A value <code>x</code> of non-interface type <code>X</code> and
|
||||
a value <code>t</code> of interface type <code>T</code> are comparable when values
|
||||
of type <code>X</code> are comparable and
|
||||
a value <code>t</code> of interface type <code>T</code> can be compared
|
||||
if type <code>X</code> is comparable and
|
||||
<code>X</code> <a href="#Implementing_an_interface">implements</a> <code>T</code>.
|
||||
They are equal if <code>t</code>'s dynamic type is identical to <code>X</code>
|
||||
and <code>t</code>'s dynamic value is equal to <code>x</code>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Struct values are comparable if all their fields are comparable.
|
||||
Struct types are comparable if all their field types are comparable.
|
||||
Two struct values are equal if their corresponding
|
||||
non-<a href="#Blank_identifier">blank</a> field values are equal.
|
||||
The fields are compared in source order, and comparison stops as
|
||||
@ -5089,23 +5091,27 @@ These terms and the result of the comparisons are defined as follows:
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Array values are comparable if values of the array element type are comparable.
|
||||
Array types are comparable if their array element types are comparable.
|
||||
Two array values are equal if their corresponding element values are equal.
|
||||
The elements are compared in ascending index order, and comparison stops
|
||||
as soon as two element values differ (or all elements have been compared).
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Type parameters are comparable if they are strictly comparable (see below).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
A comparison of two interface values with identical dynamic types
|
||||
causes a <a href="#Run_time_panics">run-time panic</a> if values
|
||||
of that type are not comparable. This behavior applies not only to direct interface
|
||||
causes a <a href="#Run_time_panics">run-time panic</a> if that type
|
||||
is not comparable. This behavior applies not only to direct interface
|
||||
value comparisons but also when comparing arrays of interface values
|
||||
or structs with interface-valued fields.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Slice, map, and function values are not comparable.
|
||||
Slice, map, and function types are not comparable.
|
||||
However, as a special case, a slice, map, or function value may
|
||||
be compared to the predeclared identifier <code>nil</code>.
|
||||
Comparison of pointer, channel, and interface values to <code>nil</code>
|
||||
@ -5126,6 +5132,30 @@ var (
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A type is <i>strictly comparable</i> if it is comparable and not an interface
|
||||
type nor composed of interface types.
|
||||
Specifically:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Boolean, numeric, string, pointer, and channel types are strictly comparable.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Struct types are strictly comparable if all their field types are strictly comparable.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Array types are strictly comparable if their array element types are strictly comparable.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Type parameters are strictly comparable if all types in their type set are strictly comparable.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="Logical_operators">Logical operators</h3>
|
||||
|
||||
<p>
|
||||
|
Loading…
Reference in New Issue
Block a user