diff options
author | Robert Findley <rfindley@google.com> | 2022-03-30 09:56:13 -0400 |
---|---|---|
committer | Cherry Mui <cherryyz@google.com> | 2022-04-06 17:10:45 +0000 |
commit | 9535031e32757d2f3b83f3f1ce116017bd06fdbe (patch) | |
tree | 5cdb37ba65c3f80c694fe366bca162b0760ecdc2 | |
parent | 2097b2d51b095296d20712f0b8b0b42a6f693f2e (diff) | |
download | go-9535031e32757d2f3b83f3f1ce116017bd06fdbe.tar.gz go-9535031e32757d2f3b83f3f1ce116017bd06fdbe.zip |
[release-branch.go1.18] go/types: don't report errors for untyped int shifts on Go < 1.13
CL 337529 introduced upfront type-checking of constant shift operands,
to avoid converting their type to uint (per the spec). However, it
had an oversight in that the checks intended for non-constant operands
still ran after the explicit checking of constant operands. As a
result, there are at least two bugs:
- When GoVersion is < 1.13, we report spurious errors for untyped
constant shift operands.
- When the operand is an untyped float constant, we still convert to
uint (this was a known bug reported in #47410).
Looking at this now, it seems clear that we can avoid both of these bugs
by simply not running the additional checks in the case of a constant
operand. However, this should be considered with some care, as shifts
are notoriously tricky.
While cherry-picking, the new test file is updated to use the go1_12
package name, following our convention for specifying language version
in the release branch.
Fixes #52032
Change-Id: Ia489cc5470b92a8187d3de0423d05b309daf47bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/396775
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 8a816d5efcc842ae92f0193aa9c1d433bd66ef31)
Reviewed-on: https://go-review.googlesource.com/c/go/+/397680
-rw-r--r-- | src/go/types/api_test.go | 2 | ||||
-rw-r--r-- | src/go/types/expr.go | 38 | ||||
-rw-r--r-- | src/go/types/testdata/fixedbugs/issue52031.go | 33 |
3 files changed, 53 insertions, 20 deletions
diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 6b05d66b10..78977ff2f0 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -330,7 +330,7 @@ func TestTypesInfo(t *testing.T) { // issue 47243 {`package issue47243_a; var x int32; var _ = x << 3`, `3`, `untyped int`}, - {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `uint`}, // issue 47410: should be untyped float + {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `untyped float`}, {`package issue47243_c; var x int32; var _ = 1 << x`, `1 << x`, `int`}, {`package issue47243_d; var x int32; var _ = 1 << x`, `1`, `int`}, {`package issue47243_e; var x int32; var _ = 1 << 2`, `1`, `untyped int`}, diff --git a/src/go/types/expr.go b/src/go/types/expr.go index e24bd60dc3..23a735ce69 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -934,28 +934,28 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { return } } - } - - // Check that RHS is otherwise at least of integer type. - switch { - case allInteger(y.typ): - if !allUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { - check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y) - x.mode = invalid - return - } - case isUntyped(y.typ): - // This is incorrect, but preserves pre-existing behavior. - // See also bug #47410. - check.convertUntyped(y, Typ[Uint]) - if y.mode == invalid { + } else { + // Check that RHS is otherwise at least of integer type. + switch { + case allInteger(y.typ): + if !allUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { + check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y) + x.mode = invalid + return + } + case isUntyped(y.typ): + // This is incorrect, but preserves pre-existing behavior. + // See also bug #47410. + check.convertUntyped(y, Typ[Uint]) + if y.mode == invalid { + x.mode = invalid + return + } + default: + check.invalidOp(y, _InvalidShiftCount, "shift count %s must be integer", y) x.mode = invalid return } - default: - check.invalidOp(y, _InvalidShiftCount, "shift count %s must be integer", y) - x.mode = invalid - return } if x.mode == constant_ { diff --git a/src/go/types/testdata/fixedbugs/issue52031.go b/src/go/types/testdata/fixedbugs/issue52031.go new file mode 100644 index 0000000000..dff2abd667 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue52031.go @@ -0,0 +1,33 @@ +// -lang=go1.12 + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package go1_12 + +type resultFlags uint + +// Example from #52031. +// +// The following shifts should not produce errors on Go < 1.13, as their +// untyped constant operands are representable by type uint. +const ( + _ resultFlags = (1 << iota) / 2 + + reportEqual + reportUnequal + reportByIgnore + reportByMethod + reportByFunc + reportByCycle +) + +// Invalid cases. +var x int = 1 +var _ = (8 << x /* ERROR "signed shift count .* requires go1.13 or later" */) + +const _ = (1 << 1.2 /* ERROR "truncated to uint" */) + +var y float64 +var _ = (1 << y /* ERROR "must be integer" */) |