summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-01-31 08:21:34 -0800
committerPaul Phillips <paulp@improving.org>2012-01-31 08:51:42 -0800
commit147e9eaf3814738f339b020e701a160ba2f68b60 (patch)
treee76a078289a446c69e5c6f952e71e75033553ae6
parent263aa2ead1f599f48b218027eb9550745fef43f1 (diff)
downloadscala-147e9eaf3814738f339b020e701a160ba2f68b60.tar.gz
scala-147e9eaf3814738f339b020e701a160ba2f68b60.tar.bz2
scala-147e9eaf3814738f339b020e701a160ba2f68b60.zip
Improved warning for insensible comparisons.
Utilize knowledge of case class synthetic equals to rule out some comparisons statically. Closes SI-5426.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala11
-rw-r--r--test/files/neg/checksensible.check5
-rw-r--r--test/files/neg/t5426.check13
-rw-r--r--test/files/neg/t5426.flags1
-rw-r--r--test/files/neg/t5426.scala10
5 files changed, 35 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index a99d09173e..a6c2f75d5e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1034,10 +1034,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
/** Symbols which limit the warnings we can issue since they may be value types */
val isMaybeValue = Set(AnyClass, AnyRefClass, AnyValClass, ObjectClass, ComparableClass, JavaSerializableClass)
- // Whether def equals(other: Any) is overridden
- def isUsingDefaultEquals = {
+ // Whether def equals(other: Any) is overridden or synthetic
+ def isUsingWarnableEquals = {
val m = receiver.info.member(nme.equals_)
- (m == Object_equals) || (m == Any_equals)
+ (m == Object_equals) || (m == Any_equals) || (m.isSynthetic && m.owner.isCase)
}
// Whether this == or != is one of those defined in Any/AnyRef or an overload from elsewhere.
def isUsingDefaultScalaOp = {
@@ -1045,7 +1045,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
(s == Object_==) || (s == Object_!=) || (s == Any_==) || (s == Any_!=)
}
// Whether the operands+operator represent a warnable combo (assuming anyrefs)
- def isWarnable = isReferenceOp || (isUsingDefaultEquals && isUsingDefaultScalaOp)
+ // Looking for comparisons performed with ==/!= in combination with either an
+ // equals method inherited from Object or a case class synthetic equals (for
+ // which we know the logic.)
+ def isWarnable = isReferenceOp || (isUsingDefaultScalaOp && isUsingWarnableEquals)
def isEitherNullable = (NullClass.tpe <:< receiver.info) || (NullClass.tpe <:< actual.info)
def isBoolean(s: Symbol) = unboxedValueClass(s) == BooleanClass
def isUnit(s: Symbol) = unboxedValueClass(s) == UnitClass
diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check
index 0881205bb4..d785179a56 100644
--- a/test/files/neg/checksensible.check
+++ b/test/files/neg/checksensible.check
@@ -28,6 +28,9 @@ checksensible.scala:27: error: comparing values of types Int and Unit using `=='
checksensible.scala:29: error: comparing values of types Int and String using `==' will always yield false
1 == "abc"
^
+checksensible.scala:33: error: comparing values of types Some[Int] and Int using `==' will always yield false
+ Some(1) == 1 // as above
+ ^
checksensible.scala:38: error: comparing a fresh object using `==' will always yield false
new AnyRef == 1
^
@@ -94,4 +97,4 @@ checksensible.scala:84: error: comparing values of types EqEqRefTest.this.C3 and
checksensible.scala:95: error: comparing values of types Unit and Int using `!=' will always yield true
while ((c = in.read) != -1)
^
-32 errors found
+33 errors found
diff --git a/test/files/neg/t5426.check b/test/files/neg/t5426.check
new file mode 100644
index 0000000000..d9e192d3f0
--- /dev/null
+++ b/test/files/neg/t5426.check
@@ -0,0 +1,13 @@
+t5426.scala:2: error: comparing values of types Some[Int] and Int using `==' will always yield false
+ def f1 = Some(5) == 5
+ ^
+t5426.scala:3: error: comparing values of types Int and Some[Int] using `==' will always yield false
+ def f2 = 5 == Some(5)
+ ^
+t5426.scala:8: error: comparing values of types Int and Some[Int] using `==' will always yield false
+ (x1 == x2)
+ ^
+t5426.scala:9: error: comparing values of types Some[Int] and Int using `==' will always yield false
+ (x2 == x1)
+ ^
+four errors found
diff --git a/test/files/neg/t5426.flags b/test/files/neg/t5426.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t5426.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t5426.scala b/test/files/neg/t5426.scala
new file mode 100644
index 0000000000..f2fb5cc12c
--- /dev/null
+++ b/test/files/neg/t5426.scala
@@ -0,0 +1,10 @@
+class A {
+ def f1 = Some(5) == 5
+ def f2 = 5 == Some(5)
+
+ val x1 = 5
+ val x2 = Some(5)
+
+ (x1 == x2)
+ (x2 == x1)
+}