summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala6
-rw-r--r--test/files/neg/checksensible.check48
-rw-r--r--test/files/neg/checksensible.scala6
4 files changed, 40 insertions, 26 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 654639adae..4ee717ce75 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -784,12 +784,12 @@ trait Definitions extends reflect.api.StandardDefinitions {
/** Is symbol a boxed value class, e.g. java.lang.Integer? */
def isBoxedValueClass(sym: Symbol) = boxedValueClassesSet(sym)
- /** If symbol is a value class, return the value class, with the exception
- * that BoxedUnit remains BoxedUnit. If not a value class, NoSymbol.
+ /** If symbol is a value class (boxed or not), return the unboxed
+ * value class. Otherwise, NoSymbol.
*/
def unboxedValueClass(sym: Symbol): Symbol =
if (isValueClass(sym)) sym
- else if (sym == BoxedUnitClass) sym
+ else if (sym == BoxedUnitClass) UnitClass
else boxedClass.map(_.swap).getOrElse(sym, NoSymbol)
/** Is type's symbol a numeric value class? */
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index c9237627e7..a5053eb559 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1017,7 +1017,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def typesString = normalizeAll(qual.tpe.widen)+" and "+normalizeAll(args.head.tpe.widen)
/** Symbols which limit the warnings we can issue since they may be value types */
- val isMaybeValue = Set(AnyClass, AnyRefClass, AnyValClass, ObjectClass, ComparableClass, SerializableClass)
+ val isMaybeValue = Set(AnyClass, AnyRefClass, AnyValClass, ObjectClass, ComparableClass, JavaSerializableClass)
// Whether def equals(other: Any) is overridden
def isUsingDefaultEquals = {
@@ -1035,6 +1035,7 @@ 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 isSpecial(s: Symbol) = isValueClass(unboxedValueClass(s)) || (s isSubClass ScalaNumberClass) || isMaybeValue(s)
def possibleNumericCount = onSyms(_ filter (x => isNumeric(x) || isMaybeValue(x)) size)
val nullCount = onSyms(_ filter (_ == NullClass) size)
@@ -1088,7 +1089,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
}
- if (nullCount == 0 && possibleNumericCount < 2) {
+ // possibleNumericCount is insufficient or this will warn on e.g. Boolean == j.l.Boolean
+ if (nullCount == 0 && !(isSpecial(receiver) && isSpecial(actual))) {
if (actual isSubClass receiver) ()
else if (receiver isSubClass actual) ()
// warn only if they have no common supertype below Object
diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check
index c085aa2719..d45d16165f 100644
--- a/test/files/neg/checksensible.check
+++ b/test/files/neg/checksensible.check
@@ -34,64 +34,70 @@ checksensible.scala:32: error: String and Int are unrelated: they will most like
checksensible.scala:33: error: Some[Int] and Int are unrelated: they will most likely never compare equal
Some(1) == 1 // as above
^
-checksensible.scala:35: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:38: error: comparing a fresh object using `==' will always yield false
new AnyRef == 1
^
-checksensible.scala:38: error: comparing values of types Int and Boolean using `==' will always yield false
+checksensible.scala:41: error: comparing values of types Int and Boolean using `==' will always yield false
1 == (new java.lang.Boolean(true))
^
-checksensible.scala:40: error: comparing values of types Int and Boolean using `!=' will always yield true
+checksensible.scala:43: error: comparing values of types Int and Boolean using `!=' will always yield true
1 != true
^
-checksensible.scala:41: error: comparing values of types Unit and Boolean using `==' will always yield false
+checksensible.scala:44: error: comparing values of types Unit and Boolean using `==' will always yield false
() == true
^
-checksensible.scala:42: error: comparing values of types Unit and Unit using `==' will always yield true
+checksensible.scala:45: error: comparing values of types Unit and Unit using `==' will always yield true
() == ()
^
-checksensible.scala:43: error: comparing values of types Unit and Unit using `==' will always yield true
+checksensible.scala:46: error: comparing values of types Unit and Unit using `==' will always yield true
() == println
^
-checksensible.scala:45: error: comparing values of types Int and Unit using `!=' will always yield true
+checksensible.scala:47: error: comparing values of types Unit and scala.runtime.BoxedUnit using `==' will always yield true
+ () == scala.runtime.BoxedUnit.UNIT // these should warn for always being true/false
+ ^
+checksensible.scala:48: error: comparing values of types scala.runtime.BoxedUnit and Unit using `!=' will always yield false
+ scala.runtime.BoxedUnit.UNIT != ()
+ ^
+checksensible.scala:51: error: comparing values of types Int and Unit using `!=' will always yield true
(1 != println)
^
-checksensible.scala:46: error: comparing values of types Int and Symbol using `!=' will always yield true
+checksensible.scala:52: error: comparing values of types Int and Symbol using `!=' will always yield true
(1 != 'sym)
^
-checksensible.scala:52: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:58: error: comparing a fresh object using `==' will always yield false
((x: Int) => x + 1) == null
^
-checksensible.scala:53: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:59: error: comparing a fresh object using `==' will always yield false
Bep == ((_: Int) + 1)
^
-checksensible.scala:55: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:61: error: comparing a fresh object using `==' will always yield false
new Object == new Object
^
-checksensible.scala:56: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:62: error: comparing a fresh object using `==' will always yield false
new Object == "abc"
^
-checksensible.scala:57: error: comparing a fresh object using `!=' will always yield true
+checksensible.scala:63: error: comparing a fresh object using `!=' will always yield true
new Exception() != new Exception()
^
-checksensible.scala:60: error: comparing values of types Int and Null using `==' will always yield false
+checksensible.scala:66: error: comparing values of types Int and Null using `==' will always yield false
if (foo.length == null) "plante" else "plante pas"
^
-checksensible.scala:65: error: comparing values of types Bip and Bop using `==' will always yield false
+checksensible.scala:71: error: comparing values of types Bip and Bop using `==' will always yield false
(x1 == x2)
^
-checksensible.scala:75: error: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false
+checksensible.scala:81: error: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false
c3 == z1
^
-checksensible.scala:76: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false
+checksensible.scala:82: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false
z1 == c3
^
-checksensible.scala:77: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true
+checksensible.scala:83: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true
z1 != c3
^
-checksensible.scala:78: error: comparing values of types EqEqRefTest.this.C3 and String using `!=' will always yield true
+checksensible.scala:84: error: comparing values of types EqEqRefTest.this.C3 and String using `!=' will always yield true
c3 != "abc"
^
-checksensible.scala:89: error: comparing values of types Unit and Int using `!=' will always yield true
+checksensible.scala:95: error: comparing values of types Unit and Int using `!=' will always yield true
while ((c = in.read) != -1)
^
-32 errors found
+34 errors found
diff --git a/test/files/neg/checksensible.scala b/test/files/neg/checksensible.scala
index 77b5a93f74..b6083f75e4 100644
--- a/test/files/neg/checksensible.scala
+++ b/test/files/neg/checksensible.scala
@@ -32,6 +32,9 @@ class EqEqValTest {
"abc" == 1 // warns because the lub of String and Int is Any
Some(1) == 1 // as above
+ true == new java.lang.Boolean(true) // none of these should warn
+ new java.lang.Boolean(true) == true
+
new AnyRef == 1
1 == new AnyRef // doesn't warn because it could be...
1 == (new java.lang.Integer(1)) // ...something like this
@@ -41,6 +44,9 @@ class EqEqValTest {
() == true
() == ()
() == println
+ () == scala.runtime.BoxedUnit.UNIT // these should warn for always being true/false
+ scala.runtime.BoxedUnit.UNIT != ()
+ (scala.runtime.BoxedUnit.UNIT: java.io.Serializable) != () // shouldn't warn
(1 != println)
(1 != 'sym)