summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-09-09 00:14:43 +0000
committerPaul Phillips <paulp@improving.org>2011-09-09 00:14:43 +0000
commitca15d245fd8624392756df5e79f893bea8ce53ef (patch)
tree044b7774a11c755700a8a2a8c33babce1083c6bb
parent65a785e17793e39a67a26ad30abe0a02edc5bf89 (diff)
downloadscala-ca15d245fd8624392756df5e79f893bea8ce53ef.tar.gz
scala-ca15d245fd8624392756df5e79f893bea8ce53ef.tar.bz2
scala-ca15d245fd8624392756df5e79f893bea8ce53ef.zip
Brought back unrelated type comparison warning.
Figured out how to turn it on by default, even. Closes SI-4979, no review.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala25
-rw-r--r--test/files/neg/checksensible.check48
-rw-r--r--test/files/neg/checksensible.scala5
3 files changed, 44 insertions, 34 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 0ff886dea6..1b28027bb1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -966,10 +966,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case _ => false
}
def underlyingClass(tp: Type): Symbol = {
- var sym = tp.widen.typeSymbol
- while (sym.isAbstractType)
- sym = sym.info.bounds.hi.widen.typeSymbol
- sym
+ val sym = tp.widen.typeSymbol
+ if (sym.isAbstractType) underlyingClass(sym.info.bounds.hi)
+ else sym
}
val actual = underlyingClass(args.head.tpe)
val receiver = underlyingClass(qual.tpe)
@@ -1009,8 +1008,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def nonSensible(pre: String, alwaysEqual: Boolean) =
nonSensibleWarning(pre+"values of types "+typesString, alwaysEqual)
- def unrelatedTypes() =
- unit.warning(pos, typesString + " are unrelated: should not compare equal")
+ def unrelatedTypes() = {
+ val msg = if (name == nme.EQ || name == nme.eq)
+ "never compare equal" else "always compare unequal"
+ unit.warning(pos, typesString + " are unrelated: they will most likely " + msg)
+ }
if (nullCount == 2)
nonSensible("", true) // null == null
@@ -1047,13 +1049,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
nonSensible("", false)
}
}
- // Warning on types without a parental relationship. Uncovers a lot of
- // bugs, but not always right to warn.
- if (false) {
- if (nullCount == 0 && possibleNumericCount < 2 && !(receiver isSubClass actual) && !(actual isSubClass receiver))
+
+ if (nullCount == 0 && possibleNumericCount < 2) {
+ if (actual isSubClass receiver) ()
+ else if (receiver isSubClass actual) ()
+ // warn only if they have no common supertype below Object
+ else if (ObjectClass.tpe <:< global.lub(List(actual.tpe, receiver.tpe)))
unrelatedTypes()
}
-
case _ =>
}
diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check
index 9977739196..085e00af2e 100644
--- a/test/files/neg/checksensible.check
+++ b/test/files/neg/checksensible.check
@@ -28,64 +28,70 @@ checksensible.scala:27: error: comparing values of types Int and Unit using `=='
checksensible.scala:29: error: comparing values of types Int and java.lang.String using `==' will always yield false
1 == "abc"
^
-checksensible.scala:34: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:32: error: java.lang.String and Int are unrelated: they will most likely never compare equal
+ "abc" == 1 // warns because the lub of String and Int is Any
+ ^
+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
new AnyRef == 1
^
-checksensible.scala:37: error: comparing values of types Int and java.lang.Boolean using `==' will always yield false
+checksensible.scala:38: error: comparing values of types Int and java.lang.Boolean using `==' will always yield false
1 == (new java.lang.Boolean(true))
^
-checksensible.scala:39: error: comparing values of types Int and Boolean using `!=' will always yield true
+checksensible.scala:40: error: comparing values of types Int and Boolean using `!=' will always yield true
1 != true
^
-checksensible.scala:40: error: comparing values of types Unit and Boolean using `==' will always yield false
+checksensible.scala:41: error: comparing values of types Unit and Boolean using `==' will always yield false
() == true
^
-checksensible.scala:41: error: comparing values of types Unit and Unit using `==' will always yield true
+checksensible.scala:42: error: comparing values of types Unit and Unit using `==' will always yield true
() == ()
^
-checksensible.scala:42: 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
() == println
^
-checksensible.scala:44: error: comparing values of types Int and Unit using `!=' will always yield true
+checksensible.scala:45: error: comparing values of types Int and Unit using `!=' will always yield true
(1 != println)
^
-checksensible.scala:45: error: comparing values of types Int and Symbol using `!=' will always yield true
+checksensible.scala:46: error: comparing values of types Int and Symbol using `!=' will always yield true
(1 != 'sym)
^
-checksensible.scala:51: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:52: error: comparing a fresh object using `==' will always yield false
((x: Int) => x + 1) == null
^
-checksensible.scala:52: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:53: error: comparing a fresh object using `==' will always yield false
Bep == ((_: Int) + 1)
^
-checksensible.scala:54: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:55: error: comparing a fresh object using `==' will always yield false
new Object == new Object
^
-checksensible.scala:55: error: comparing a fresh object using `==' will always yield false
+checksensible.scala:56: error: comparing a fresh object using `==' will always yield false
new Object == "abc"
^
-checksensible.scala:56: error: comparing a fresh object using `!=' will always yield true
+checksensible.scala:57: error: comparing a fresh object using `!=' will always yield true
new Exception() != new Exception()
^
-checksensible.scala:59: error: comparing values of types Int and Null using `==' will always yield false
+checksensible.scala:60: error: comparing values of types Int and Null using `==' will always yield false
if (foo.length == null) "plante" else "plante pas"
^
-checksensible.scala:64: error: comparing values of types Bip and Bop using `==' will always yield false
+checksensible.scala:65: error: comparing values of types Bip and Bop using `==' will always yield false
(x1 == x2)
^
-checksensible.scala:74: error: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false
+checksensible.scala:75: error: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false
c3 == z1
^
-checksensible.scala:75: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false
+checksensible.scala:76: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false
z1 == c3
^
-checksensible.scala:76: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true
+checksensible.scala:77: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true
z1 != c3
^
-checksensible.scala:77: error: comparing values of types EqEqRefTest.this.C3 and java.lang.String using `!=' will always yield true
+checksensible.scala:78: error: comparing values of types EqEqRefTest.this.C3 and java.lang.String using `!=' will always yield true
c3 != "abc"
^
-checksensible.scala:88: error: comparing values of types Unit and Int using `!=' will always yield true
+checksensible.scala:89: error: comparing values of types Unit and Int using `!=' will always yield true
while ((c = in.read) != -1)
^
-30 errors found
+32 errors found
diff --git a/test/files/neg/checksensible.scala b/test/files/neg/checksensible.scala
index 4872df4dfb..77b5a93f74 100644
--- a/test/files/neg/checksensible.scala
+++ b/test/files/neg/checksensible.scala
@@ -19,7 +19,7 @@ class RefEqTest {
null eq new AnyRef
}
-// 11 warnings
+// 13 warnings
class EqEqValTest {
var c = 0
@@ -29,7 +29,8 @@ class EqEqValTest {
1 == "abc"
1 == ("abc": Any) // doesn't warn because an Any may be a boxed Int
1 == (1: Any) // as above
- "abc" == 1 // doesn't generally warn since String defines an equals method, but can chatty warn
+ "abc" == 1 // warns because the lub of String and Int is Any
+ Some(1) == 1 // as above
new AnyRef == 1
1 == new AnyRef // doesn't warn because it could be...