Permalink
Browse files

SI-5779: Wrong warning message (comparing values of types Float/Doubl…

…e and Number using `==' will always yield false)

BoxesRuntime knows how to compare java.lang.Number, so we must not warn.
  • Loading branch information...
som-snytt committed May 22, 2012
1 parent f406550 commit e3b924e3e287baab36693afb92fb9988c56a57a1
@@ -404,6 +404,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val JavaSerializableClass = requiredClass[java.io.Serializable] modifyInfo fixupAsAnyTrait
lazy val ComparableClass = requiredClass[java.lang.Comparable[_]] modifyInfo fixupAsAnyTrait
lazy val JavaCloneableClass = requiredClass[java.lang.Cloneable]
+ lazy val JavaNumberClass = requiredClass[java.lang.Number]
lazy val RemoteInterfaceClass = requiredClass[java.rmi.Remote]
lazy val RemoteExceptionClass = requiredClass[java.rmi.RemoteException]
@@ -1085,13 +1085,16 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def isBoolean(s: Symbol) = unboxedValueClass(s) == BooleanClass
def isUnit(s: Symbol) = unboxedValueClass(s) == UnitClass
def isNumeric(s: Symbol) = isNumericValueClass(unboxedValueClass(s)) || (s isSubClass ScalaNumberClass)
+ def isJavaNumeric(s: Symbol) = s isSubClass JavaNumberClass
def isSpecial(s: Symbol) = isPrimitiveValueClass(unboxedValueClass(s)) || (s isSubClass ScalaNumberClass) || isMaybeValue(s)
def possibleNumericCount = onSyms(_ filter (x => isNumeric(x) || isMaybeValue(x)) size)
val nullCount = onSyms(_ filter (_ == NullClass) size)
+ var sensicality = false
def nonSensibleWarning(what: String, alwaysEqual: Boolean) = {
val msg = alwaysEqual == (name == nme.EQ || name == nme.eq)
unit.warning(pos, "comparing "+what+" using `"+name.decode+"' will always yield " + msg)
+ sensicality = true
}
def nonSensible(pre: String, alwaysEqual: Boolean) =
nonSensibleWarning(pre+"values of types "+typesString, alwaysEqual)
@@ -1123,10 +1126,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
else if (!isUnit(actual) && !isMaybeValue(actual)) // () == "abc"
nonSensiblyNeq()
}
- else if (isNumeric(receiver)) {
- if (!isNumeric(actual) && !forMSIL)
+ else if (isNumeric(receiver) || (!forMSIL && isJavaNumeric(receiver))) {
+ if (!isNumeric(actual) && !forMSIL && !isJavaNumeric(actual))
if (isUnit(actual) || isBoolean(actual) || !isMaybeValue(actual)) // 5 == "abc"
nonSensiblyNeq()
+ sensicality = true
}
else if (isWarnable && !isCaseEquals) {
if (isNew(qual)) // new X == y
@@ -1142,7 +1146,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
// possibleNumericCount is insufficient or this will warn on e.g. Boolean == j.l.Boolean
- if (isWarnable && nullCount == 0 && !(isSpecial(receiver) && isSpecial(actual))) {
+ if (!sensicality && isWarnable && nullCount == 0 && !(isSpecial(receiver) && isSpecial(actual))) {
// better to have lubbed and lost
def warnIfLubless(): Unit = {
val common = global.lub(List(actual.tpe, receiver.tpe))
@@ -1155,7 +1159,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
if (isCaseEquals) {
def thisCase = receiver.info.member(nme.equals_).owner
actual.info.baseClasses.find(_.isCase) match {
- case Some(p) if (p != thisCase) => nonSensible("case class ", false)
+ case Some(p) if p != thisCase => nonSensible("case class ", false)
case None =>
// stronger message on (Some(1) == None)
//if (receiver.isCase && receiver.isEffectivelyFinal && !(receiver isSubClass actual)) nonSensiblyNeq()
@@ -0,0 +1,13 @@
+
+object Test {
+ def main(args: Array[String]) {
+ val d: Double = (BigInt(1) << 64).toDouble
+ val f: Float = d.toFloat
+ val n: java.lang.Number = d.toFloat
+ assert (d == f) // ok
+ assert (d == n) // was: comparing values of types Double and Number using `==' will always yield false
+ assert (n == d) // was: Number and Double are unrelated: they will most likely never compare equal
+ assert (f == n)
+ assert (n == f)
+ }
+}

0 comments on commit e3b924e

Please sign in to comment.