Skip to content

Int shift Long - Scala does not agree with Java on the runtime semantics #9516

Closed
@scabug

Description

@scabug

For any of the three shift operators (<<, >>> and >>), when the left operand is an Int (or Byte or Short, I guess) but the right operand is a Long, the runtime semantics produced by scalac are not the same as those produced by javac for equivalent operations.

Reproduction: compile the attached Foo.java and Bar.scala with javac and scalac respectively, and execute the code. The programs are equivalent at the source level, but they don't produce the same results.

Java produces:
271601776
271601776
271601776
271601776
151323393
151323393
151323393
151323393
-117112063
-117112063
-117112063
-117112063

but Scala produces:
0
0
0
0
268435455
268435455
268435455
268435455
-1
-1
-1
-1

To make the Scala program behave the same as the Java program, I have to explicitly add .toInts to the righ-hand-side of all shift operations, e.g., x << y.toInt instead of x << y. Conversely, to make the Java program behave the same as the Scala program, I have to replace x << y by (int) ((long) x << y)).

The difference, in practice, is that, in Java, the rhs is computed modulo 32, as expected for a shift operation returning an Int, whereas in Scala, the rhs is computed modulo 64.

This misbehavior has apparently lived on in all versions of Scala. I would understand if we cannot fix this in 2.11 for compatibility reasons, but we should fix this for 2.12.

The Bar.scala file can be trivially turned into a partest test, using as checkfile the output of Java listed above.

Related bug that was fixed in 2.12.0-M1: #8462

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions