mirror of
https://github.com/golang/go
synced 2024-11-26 16:57:14 -07:00
spec: clarify context type for certain non-constant shifts
The spec is not conclusive about whether a non-constant shift of certain untyped constant left operands is valid when the shift expression appears as an index in an index or slice expression, or as a size in a `make` function call. Despite identical spec rules in all these cases, cmd/compile accepts make([]byte, 1.0 << s) but pronounces an error for a[1.0 << s] (go/types accepts both). This change clarifies the spec by explicitly stating that an untyped constant left operand in a non-constant shift (1.0 in the above examples) will be given type `int` in these contexts. A separate issue #21693 addresses the cmd/compile bug. Fixes #14844. Change-Id: I4b52125e487a607fae377fcbed55463cdce9836c Reviewed-on: https://go-review.googlesource.com/60230 Reviewed-by: Russ Cox <rsc@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
ec359643a1
commit
9690d245d5
@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of August 30, 2017",
|
||||
"Subtitle": "Version of September 1, 2017",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@ -2975,12 +2975,12 @@ The following rules apply:
|
||||
If <code>a</code> is not a map:
|
||||
</p>
|
||||
<ul>
|
||||
<li>the index <code>x</code> must be of integer type or untyped;
|
||||
it is <i>in range</i> if <code>0 <= x < len(a)</code>,
|
||||
<li>the index <code>x</code> must be of integer type or an untyped constant</li>
|
||||
<li>a constant index must be non-negative and
|
||||
<a href="#Representability">representable</a> by a value of type <code>int</code></li>
|
||||
<li>a constant index that is untyped is given type <code>int</code></li>
|
||||
<li>the index <code>x</code> is <i>in range</i> if <code>0 <= x < len(a)</code>,
|
||||
otherwise it is <i>out of range</i></li>
|
||||
<li>a <a href="#Constants">constant</a> index must be non-negative
|
||||
and <a href="#Representability">representable</a> by a value
|
||||
of type <code>int</code></li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
@ -3450,18 +3450,20 @@ replaced by its left operand alone.
|
||||
|
||||
<pre>
|
||||
var s uint = 33
|
||||
var i = 1<<s // 1 has type int
|
||||
var j int32 = 1<<s // 1 has type int32; j == 0
|
||||
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
|
||||
var m int = 1.0<<s // 1.0 has type int; m == 0 if ints are 32bits in size
|
||||
var n = 1.0<<s == j // 1.0 has type int32; n == true
|
||||
var o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size
|
||||
var p = 1<<s == 1<<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
|
||||
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
|
||||
var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift
|
||||
var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift
|
||||
var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
|
||||
var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression
|
||||
var i = 1<<s // 1 has type int
|
||||
var j int32 = 1<<s // 1 has type int32; j == 0
|
||||
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
|
||||
var m int = 1.0<<s // 1.0 has type int; m == 0 if ints are 32bits in size
|
||||
var n = 1.0<<s == j // 1.0 has type int32; n == true
|
||||
var o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size
|
||||
var p = 1<<s == 1<<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
|
||||
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
|
||||
var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift
|
||||
var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift
|
||||
var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
|
||||
var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression
|
||||
var x = a[1.0<<s] // 1.0 has type int; x == a[0] if ints are 32bits in size
|
||||
var a = make([]byte, 1.0<<s) // 1.0 has type int; len(a) == 0 if ints are 32bits in size
|
||||
</pre>
|
||||
|
||||
|
||||
@ -5724,9 +5726,10 @@ make(T, n) channel buffered channel of type T, buffer size n
|
||||
|
||||
|
||||
<p>
|
||||
The size arguments <code>n</code> and <code>m</code> must be of integer type or untyped.
|
||||
A <a href="#Constants">constant</a> size argument must be non-negative and
|
||||
<a href="#Representability">representable</a> by a value of type <code>int</code>.
|
||||
Each of the size arguments <code>n</code> and <code>m</code> must be of integer type
|
||||
or an untyped <a href="#Constants">constant</a>.
|
||||
A constant size argument must be non-negative and <a href="#Representability">representable</a>
|
||||
by a value of type <code>int</code>; if it is an untyped constant it is given type <code>int</code>.
|
||||
If both <code>n</code> and <code>m</code> are provided and are constant, then
|
||||
<code>n</code> must be no larger than <code>m</code>.
|
||||
If <code>n</code> is negative or larger than <code>m</code> at run time,
|
||||
|
Loading…
Reference in New Issue
Block a user