diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2015-07-29 13:29:57 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-07-29 14:13:22 +1000 |
commit | ec95e534a213a6ea760aa31c507d122ce449890a (patch) | |
tree | 26683be8f4c387085d7ce7a2ddf8586ee609087c /test/files/run | |
parent | 0e9525aa618a2eca143a1c7379ff1e6efd23b86e (diff) | |
download | scala-ec95e534a213a6ea760aa31c507d122ce449890a.tar.gz scala-ec95e534a213a6ea760aa31c507d122ce449890a.tar.bz2 scala-ec95e534a213a6ea760aa31c507d122ce449890a.zip |
SI-9422 Fix incorrect constant propagation
The ConstantOptimization phase uses abstract interpretation
to track what is known about values, and then to use this information
to optimize away tests with a statically known result.
Constant propagation was added under -optimize in Scala 2.11.0-M3, in
PR #2214.
For example, we might know that a variable must hold one of a set
of values (`Possible`). Or, we could track that it must *not*
be of of a set of value (`Impossible`).
The test case in the bug report was enough to create comparison:
v1 == v2 // where V1 = Possible(Set(true, false))
// V2 = Possible(Set(true, false))
This test was considered to be always true, due to a bug in
`Possible#mightNotEqual`. The only time we can be sure that
`Possible(p1) mightNotEquals Possible(p2)` is if
`p1` and `p2` are the same singleton set. This commit changes
this method to implement this logic.
The starting assumption for all values is currently
`Impossible(Set())`, although it would also be reasonable to represent
an unknown boolean variable as `Possible(Set(true, false))`, given
the finite and small domain.
I tried to change the starting assumption for boolean locals in
exactly this manner, and that brings the bug into sharp focus.
Under this patch:
https://github.com/retronym/scala/commit/e564fe522d
This code:
def test(a: Boolean, b: Boolean) = a == b
Compiles to:
public boolean test(boolean, boolean);
Code:
0: iconst_1
1: ireturn
Note: the enclosed test case does not list `-optimize` in a `.flags`
file, I'm relying on that being passed in by the validation build.
I've tested locally with that option, though.
Diffstat (limited to 'test/files/run')
-rw-r--r-- | test/files/run/t9422.scala | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/test/files/run/t9422.scala b/test/files/run/t9422.scala new file mode 100644 index 0000000000..5ca2e8daaa --- /dev/null +++ b/test/files/run/t9422.scala @@ -0,0 +1,11 @@ +class Test(val x: Long) { + def sameDirection(y: Long): Boolean = + (y == 0 || x == 0 || ((y > 0) == (x > 0))) +} + +object Test { + def main(args: Array[String]) { + val b = new Test(1L) + assert(!b.sameDirection(-1L)) + } +} |