Skip to content

Commit b40831b

Browse files
committed
spec: explicitly define notion of "representability" (clarification)
Throughout the spec we use the notion of a constant x being representable by a value of type T. While intuitively clear, at least for floating-point and complex constants types, the concept was not well-defined. In the section on Conversions there was an extra rule for floating-point types only and it missed the case of floating-point values overflowing to an infinity after rounding. Since the concept is important to Go, and a compiler most certainly will have a function to test "representability", it seems warranted to define the term explicitly in the spec. This change introduces a new entry "Representability" under the section on "Properties of types and values", and defines the term explicitly, together with examples. The phrase used is "representable by" rather than "representable as" because the former use is prevalent in the spec. Additionally, it clarifies that a floating-point constant that overflows to an infinity after rounding is never representable by a value of a floating-point type, even though infinities are valid values of IEEE floating point types. This is required because there are not infinite value constants in the language (like there is also no -0.0) and representability also matters for constant conversions. This is not a language change, and type-checkers have been following this rule before. The change also introduces links throughout the spec to the new section as appropriate and removes duplicate text and examples elsewhere (Constants and Conversions sections), leading to simplifications in the relevant paragraphs. Fixes #15389. Change-Id: I8be0e071552df0f18998ef4c5ef521f64ffe8c44 Reviewed-on: https://go-review.googlesource.com/57530 Reviewed-by: Rob Pike <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
1 parent 25bbb69 commit b40831b

File tree

1 file changed

+80
-37
lines changed

1 file changed

+80
-37
lines changed

doc/go_spec.html

Lines changed: 80 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -577,11 +577,7 @@ <h2 id="Constants">Constants</h2>
577577
<a href="#Assignments">assignment</a> or as an
578578
operand in an <a href="#Expressions">expression</a>.
579579
It is an error if the constant value
580-
cannot be represented as a value of the respective type.
581-
For instance, <code>3.0</code> can be given any integer or any
582-
floating-point type, while <code>2147483648.0</code> (equal to <code>1&lt;&lt;31</code>)
583-
can be given the types <code>float32</code>, <code>float64</code>, or <code>uint32</code> but
584-
not <code>int32</code> or <code>string</code>.
580+
cannot be <a href="#Representability">represented</a> as a value of the respective type.
585581
</p>
586582

587583
<p>
@@ -861,7 +857,8 @@ <h3 id="Array_types">Array types</h3>
861857

862858
<p>
863859
The length is part of the array's type; it must evaluate to a
864-
non-negative <a href="#Constants">constant</a> representable by a value
860+
non-negative <a href="#Constants">constant</a>
861+
<a href="#Representability">representable</a> by a value
865862
of type <code>int</code>.
866863
The length of array <code>a</code> can be discovered
867864
using the built-in function <a href="#Length_and_capacity"><code>len</code></a>.
@@ -1514,7 +1511,7 @@ <h3 id="Assignability">Assignability</h3>
15141511

15151512
<p>
15161513
A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
1517-
("<code>x</code> is assignable to <code>T</code>") in any of these cases:
1514+
("<code>x</code> is assignable to <code>T</code>") if one of the following conditions applies:
15181515
</p>
15191516

15201517
<ul>
@@ -1540,12 +1537,68 @@ <h3 id="Assignability">Assignability</h3>
15401537
is a pointer, function, slice, map, channel, or interface type.
15411538
</li>
15421539
<li>
1543-
<code>x</code> is an untyped <a href="#Constants">constant</a> representable
1540+
<code>x</code> is an untyped <a href="#Constants">constant</a>
1541+
<a href="#Representability">representable</a>
15441542
by a value of type <code>T</code>.
15451543
</li>
15461544
</ul>
15471545

15481546

1547+
<h3 id="Representability">Representability</h3>
1548+
1549+
<p>
1550+
A <a href="#Constants">constant</a> <code>x</code> is <i>representable</i>
1551+
by a value of type <code>T</code> if one of the following conditions applies:
1552+
</p>
1553+
1554+
<ul>
1555+
<li>
1556+
<code>x</code> is in the set of values <a href="#Types">determined</a> by <code>T</code>.
1557+
</li>
1558+
1559+
<li>
1560+
<code>T</code> is a floating-point type and <code>x</code> can be rounded to <code>T</code>'s
1561+
precision without overflow. Rounding uses IEEE 754 round-to-even rules but with an IEEE
1562+
negative zero further simplified to an unsigned zero. Note that constant values never result
1563+
in an IEEE negative zero, NaN, or infinity.
1564+
</li>
1565+
1566+
<li>
1567+
<code>T</code> is a complex type, and <code>x</code>'s
1568+
<a href="#Complex_numbers">components</a> <code>real(x)</code> and <code>imag(x)</code>
1569+
are representable by values of <code>T</code>'s component type (<code>float32</code> or
1570+
<code>float64</code>).
1571+
</li>
1572+
</ul>
1573+
1574+
<pre>
1575+
x T x is representable by a value of T because
1576+
1577+
'a' byte 97 is in the set of byte values
1578+
97 rune rune is an alias for int32, and 97 is in the set of 32-bit integers
1579+
"foo" string "foo" is in the set of string values
1580+
1024 int16 1024 is in the set of 16-bit integers
1581+
42.0 byte 42 is in the set of unsigned 8-bit integers
1582+
1e10 uint64 10000000000 is in the set of unsigned 64-bit integers
1583+
2.718281828459045 float32 2.718281828459045 rounds to 2.7182817 which is in the set of float32 values
1584+
-1e-1000 float64 -1e-1000 rounds to IEEE -0.0 which is further simplified to 0.0
1585+
0i int 0 is an integer value
1586+
(42 + 0i) float32 42.0 (with zero imaginary part) is in the set of float32 values
1587+
</pre>
1588+
1589+
<pre>
1590+
x T x is not representable by a value of T because
1591+
1592+
0 bool 0 is not in the set of boolean values
1593+
'a' string 'a' is a rune, it is not in the set of string values
1594+
1024 byte 1024 is not in the set of unsigned 8-bit integers
1595+
-1 uint16 -1 is not in the set of unsigned 16-bit integers
1596+
1.1 int 1.1 is not an integer value
1597+
42i float32 (0 + 42i) is not in the set of float32 values
1598+
1e1000 float64 1e1000 overflows to IEEE +Inf after rounding
1599+
</pre>
1600+
1601+
15491602
<h2 id="Blocks">Blocks</h2>
15501603

15511604
<p>
@@ -2348,7 +2401,8 @@ <h3 id="Composite_literals">Composite literals</h3>
23482401
its position in the array.
23492402
</li>
23502403
<li>An element with a key uses the key as its index. The
2351-
key must be a non-negative constant representable by
2404+
key must be a non-negative constant
2405+
<a href="#Representability">representable</a> by
23522406
a value of type <code>int</code>; and if it is typed
23532407
it must be of integer type.
23542408
</li>
@@ -2925,7 +2979,8 @@ <h3 id="Index_expressions">Index expressions</h3>
29252979
it is <i>in range</i> if <code>0 &lt;= x &lt; len(a)</code>,
29262980
otherwise it is <i>out of range</i></li>
29272981
<li>a <a href="#Constants">constant</a> index must be non-negative
2928-
and representable by a value of type <code>int</code>
2982+
and <a href="#Representability">representable</a> by a value
2983+
of type <code>int</code></li>
29292984
</ul>
29302985

29312986
<p>
@@ -3075,7 +3130,8 @@ <h4>Simple slice expressions</h4>
30753130
<code>0</code> &lt;= <code>low</code> &lt;= <code>high</code> &lt;= <code>len(a)</code>,
30763131
otherwise they are <i>out of range</i>.
30773132
For slices, the upper index bound is the slice capacity <code>cap(a)</code> rather than the length.
3078-
A <a href="#Constants">constant</a> index must be non-negative and representable by a value of type
3133+
A <a href="#Constants">constant</a> index must be non-negative and
3134+
<a href="#Representability">representable</a> by a value of type
30793135
<code>int</code>; for arrays or constant strings, constant indices must also be in range.
30803136
If both indices are constant, they must satisfy <code>low &lt;= high</code>.
30813137
If the indices are out of range at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
@@ -3135,7 +3191,8 @@ <h4>Full slice expressions</h4>
31353191
<p>
31363192
The indices are <i>in range</i> if <code>0 &lt;= low &lt;= high &lt;= max &lt;= cap(a)</code>,
31373193
otherwise they are <i>out of range</i>.
3138-
A <a href="#Constants">constant</a> index must be non-negative and representable by a value of type
3194+
A <a href="#Constants">constant</a> index must be non-negative and
3195+
<a href="#Representability">representable</a> by a value of type
31393196
<code>int</code>; for arrays, constant indices must also be in range.
31403197
If multiple indices are constant, the constants that are present must be in range relative to each
31413198
other.
@@ -3384,7 +3441,8 @@ <h3 id="Operators">Operators</h3>
33843441

33853442
<p>
33863443
The right operand in a shift expression must have unsigned integer type
3387-
or be an untyped constant representable by a value of type <code>uint</code>.
3444+
or be an untyped constant <a href="#Representability">representable</a> by a
3445+
value of type <code>uint</code>.
33883446
If the left operand of a non-constant shift expression is an untyped constant,
33893447
it is first converted to the type it would assume if the shift expression were
33903448
replaced by its left operand alone.
@@ -3877,30 +3935,14 @@ <h3 id="Conversions">Conversions</h3>
38773935

38783936
<p>
38793937
A <a href="#Constants">constant</a> value <code>x</code> can be converted to
3880-
type <code>T</code> in any of these cases:
3938+
type <code>T</code> if <code>x</code> is <a href="#Representability">representable</a>
3939+
by a value of <code>T</code>.
3940+
As a special case, an integer constant <code>x</code> can be converted to a
3941+
<a href="#String_types">string type</a> using the
3942+
<a href="#Conversions_to_and_from_a_string_type">same rule</a>
3943+
as for non-constant <code>x</code>.
38813944
</p>
38823945

3883-
<ul>
3884-
<li>
3885-
<code>x</code> is representable by a value of type <code>T</code>.
3886-
</li>
3887-
<li>
3888-
<code>x</code> is a floating-point constant,
3889-
<code>T</code> is a floating-point type,
3890-
and <code>x</code> is representable by a value
3891-
of type <code>T</code> after rounding using
3892-
IEEE 754 round-to-even rules, but with an IEEE <code>-0.0</code>
3893-
further rounded to an unsigned <code>0.0</code>.
3894-
The constant <code>T(x)</code> is the rounded value.
3895-
</li>
3896-
<li>
3897-
<code>x</code> is an integer constant and <code>T</code> is a
3898-
<a href="#String_types">string type</a>.
3899-
The <a href="#Conversions_to_and_from_a_string_type">same rule</a>
3900-
as for non-constant <code>x</code> applies in this case.
3901-
</li>
3902-
</ul>
3903-
39043946
<p>
39053947
Converting a constant yields a typed constant as result.
39063948
</p>
@@ -4187,7 +4229,8 @@ <h3 id="Constant_expressions">Constant expressions</h3>
41874229
</pre>
41884230

41894231
<p>
4190-
The values of <i>typed</i> constants must always be accurately representable as values
4232+
The values of <i>typed</i> constants must always be accurately
4233+
<a href="#Representability">representable</a> by values
41914234
of the constant type. The following constant expressions are illegal:
41924235
</p>
41934236

@@ -5683,7 +5726,7 @@ <h3 id="Making_slices_maps_and_channels">Making slices, maps and channels</h3>
56835726
<p>
56845727
The size arguments <code>n</code> and <code>m</code> must be of integer type or untyped.
56855728
A <a href="#Constants">constant</a> size argument must be non-negative and
5686-
representable by a value of type <code>int</code>.
5729+
<a href="#Representability">representable</a> by a value of type <code>int</code>.
56875730
If both <code>n</code> and <code>m</code> are provided and are constant, then
56885731
<code>n</code> must be no larger than <code>m</code>.
56895732
If <code>n</code> is negative or larger than <code>m</code> at run time,

0 commit comments

Comments
 (0)