From 9690d245d56d547c40dac269140dcddc6eb80904 Mon Sep 17 00:00:00 2001 From: griesemer Date: Wed, 30 Aug 2017 15:10:12 +0200 Subject: [PATCH] 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 Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 45 ++++++++++++++++++++++++--------------------- 1 file 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 @@ @@ -2975,12 +2975,12 @@ The following rules apply: If a is not a map:

    -
  • the index x must be of integer type or untyped; - it is in range if 0 <= x < len(a), +
  • the index x must be of integer type or an untyped constant
  • +
  • a constant index must be non-negative and + representable by a value of type int
  • +
  • a constant index that is untyped is given type int
  • +
  • the index x is in range if 0 <= x < len(a), otherwise it is out of range
  • -
  • a constant index must be non-negative - and representable by a value - of type int

@@ -3450,18 +3450,20 @@ replaced by its left operand alone.

 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
 
@@ -5724,9 +5726,10 @@ make(T, n) channel buffered channel of type T, buffer size n

-The size arguments n and m must be of integer type or untyped. -A constant size argument must be non-negative and -representable by a value of type int. +Each of the size arguments n and m must be of integer type +or an untyped constant. +A constant size argument must be non-negative and representable +by a value of type int; if it is an untyped constant it is given type int. If both n and m are provided and are constant, then n must be no larger than m. If n is negative or larger than m at run time, -- 2.50.0