From 9535031e32757d2f3b83f3f1ce116017bd06fdbe Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Wed, 30 Mar 2022 09:56:13 -0400 Subject: [PATCH] [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 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot (cherry picked from commit 8a816d5efcc842ae92f0193aa9c1d433bd66ef31) Reviewed-on: https://go-review.googlesource.com/c/go/+/397680 --- src/go/types/api_test.go | 2 +- src/go/types/expr.go | 38 +++++++++---------- src/go/types/testdata/fixedbugs/issue52031.go | 33 ++++++++++++++++ 3 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 src/go/types/testdata/fixedbugs/issue52031.go 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" */) -- 2.50.0