diff options
-rw-r--r-- | src/reflect/scala/reflect/internal/Constants.scala | 12 | ||||
-rw-r--r-- | test/files/run/t6331.check | 23 | ||||
-rw-r--r-- | test/files/run/t6331.scala | 63 |
3 files changed, 96 insertions, 2 deletions
diff --git a/src/reflect/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala index e5a543da46..4d512e3864 100644 --- a/src/reflect/scala/reflect/internal/Constants.scala +++ b/src/reflect/scala/reflect/internal/Constants.scala @@ -83,8 +83,16 @@ trait Constants extends api.Constants { */ override def equals(other: Any): Boolean = other match { case that: Constant => - this.tag == that.tag && - (this.value == that.value || this.isNaN && that.isNaN) + // Consider two NaNs to be identical, despite non-equality + // Consider -0d to be distinct from 0d, despite equality + import java.lang.Double.doubleToRawLongBits + import java.lang.Float.floatToRawIntBits + + this.tag == that.tag && ((value, that.value) match { + case (f1: Float, f2: Float) => floatToRawIntBits(f1) == floatToRawIntBits(f2) + case (d1: Double, d2: Double) => doubleToRawLongBits(d1) == doubleToRawLongBits(d2) + case (v1, v2) => v1 == v2 + }) case _ => false } diff --git a/test/files/run/t6331.check b/test/files/run/t6331.check new file mode 100644 index 0000000000..9bf3f7823a --- /dev/null +++ b/test/files/run/t6331.check @@ -0,0 +1,23 @@ + () == () + true == true + true != false + false != true + 0.toByte == 0.toByte + 0.toByte != 1.toByte + 0.toShort == 0.toShort + 0.toShort != 1.toShort + 0 == 0 + 0 != 1 + 0L == 0L + 0L != 1L + 0.0f == 0.0f + 0.0f != -0.0f + -0.0f != 0.0f + NaNf == NaNf + 0.0d == 0.0d + 0.0d != -0.0d + -0.0d != 0.0d + NaNd == NaNd + 0 != 0.0d + 0 != 0L + 0.0d != 0.0f diff --git a/test/files/run/t6331.scala b/test/files/run/t6331.scala new file mode 100644 index 0000000000..e9ed96fad3 --- /dev/null +++ b/test/files/run/t6331.scala @@ -0,0 +1,63 @@ +import scala.tools.partest._ +import java.io._ +import scala.tools.nsc._ +import scala.tools.nsc.util.CommandLineParser +import scala.tools.nsc.{Global, Settings, CompilerCommand} +import scala.tools.nsc.reporters.ConsoleReporter + +// Test of Constant#equals, which must must account for floating point intricacies. +object Test extends DirectTest { + + override def code = "" + + override def show() { + val global = newCompiler() + import global._ + + def check(c1: Any, c2: Any): Unit = { + val equal = Constant(c1) == Constant(c2) + def show(a: Any) = "" + a + (a match { + case _: Byte => ".toByte" + case _: Short => ".toShort" + case _: Long => "L" + case _: Float => "f" + case _: Double => "d" + case _ => "" + }) + val op = if (equal) "==" else "!=" + println(f"${show(c1)}%12s $op ${show(c2)}") + } + + check((), ()) + + check(true, true) + check(true, false) + check(false, true) + + check(0.toByte, 0.toByte) + check(0.toByte, 1.toByte) + + check(0.toShort, 0.toShort) + check(0.toShort, 1.toShort) + + check(0, 0) + check(0, 1) + + check(0L, 0L) + check(0L, 1L) + + check(0f, 0f) + check(0f, -0f) + check(-0f, 0f) + check(Float.NaN, Float.NaN) + + check(0d, 0d) + check(0d, -0d) + check(-0d, 0d) + check(Double.NaN, Double.NaN) + + check(0, 0d) + check(0, 0L) + check(0d, 0f) + } +} |