diff options
author | griesemer <gri@golang.org> | 2017-08-30 15:10:12 +0200 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2017-09-01 15:46:24 +0000 |
commit | 9690d245d56d547c40dac269140dcddc6eb80904 (patch) | |
tree | 97bc3446c1c47b6bc549f3a715f2ed699bb62f7e /doc/go_spec.html | |
parent | ec359643a1f663c5283a81410f003f8dab60d46e (diff) | |
download | go-9690d245d56d547c40dac269140dcddc6eb80904.tar.gz go-9690d245d56d547c40dac269140dcddc6eb80904.zip |
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>
Diffstat (limited to 'doc/go_spec.html')
-rw-r--r-- | doc/go_spec.html | 45 |
1 files changed, 24 insertions, 21 deletions
diff --git a/doc/go_spec.html b/doc/go_spec.html index 80de0f45a6..ba0a475746 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -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, |