diff --git a/go/types/expr.go b/go/types/expr.go index c7a28570..57d0cbee 100644 --- a/go/types/expr.go +++ b/go/types/expr.go @@ -546,7 +546,13 @@ func (check *checker) shift(x, y *operand, op token.Token) { x.mode = invalid return } - // everything's ok + // The lhs is representable as an integer but may not be an integer + // (e.g., 2.0, an untyped float) - this can only happen for untyped + // non-integer numeric constants. Correct the type so that the shift + // result is of integer type. + if !isInteger(x.typ) { + x.typ = Typ[UntypedInt] + } x.val = exact.Shift(x.val, op, uint(s)) return } diff --git a/go/types/stdlib_test.go b/go/types/stdlib_test.go index e7d8dce5..f371ceaa 100644 --- a/go/types/stdlib_test.go +++ b/go/types/stdlib_test.go @@ -63,10 +63,6 @@ func TestStdtest(t *testing.T) { case "map1.go": // TODO(gri) fix map key checking continue - case "shift2.go": - // TODO(gri) fix constant shift expression error - // (default type for 1.0<<1 is int, not float64). - continue case "sizeof.go", "switch.go": // TODO(gri) tone down duplicate checking in expression switches continue diff --git a/go/types/testdata/shifts.src b/go/types/testdata/shifts.src index bea4d233..62a5e225 100644 --- a/go/types/testdata/shifts.src +++ b/go/types/testdata/shifts.src @@ -4,8 +4,31 @@ package shifts +func shifts0() { + // basic constant shifts + const ( + s = 10 + _ = 0<<0 + _ = 1<