summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-11-30 17:13:52 +0000
committerPaul Phillips <paulp@improving.org>2010-11-30 17:13:52 +0000
commit81f38907b838caa64d26b4ea49efe938a3d0673f (patch)
tree06d272e24be36f359be3ea8b788491f0f26c30fd /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
parent4be5e11cccace4974ed9a449052455392570139f (diff)
downloadscala-81f38907b838caa64d26b4ea49efe938a3d0673f.tar.gz
scala-81f38907b838caa64d26b4ea49efe938a3d0673f.tar.bz2
scala-81f38907b838caa64d26b4ea49efe938a3d0673f.zip
Found several minor thigns wrong with checkSens...
Found several minor thigns wrong with checkSensible, which tries to issue warnings for comparisons which will always be true or false. No review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala59
1 files changed, 39 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index f12d7939ea..3af22264ab 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -870,24 +870,29 @@ abstract class RefChecks extends InfoTransform {
sym = sym.info.bounds.hi.widen.typeSymbol
sym
}
- val actual = underlyingClass(args.head.tpe)
+ val actual = underlyingClass(args.head.tpe)
val receiver = underlyingClass(qual.tpe)
+ /** Symbols which limit the warnings we can issue since they may be value types */
+ val isMaybeValue = Set(AnyClass, AnyRefClass, AnyValClass, ObjectClass, ComparableClass, SerializableClass)
+
// Whether def equals(other: Any) is overridden
def isUsingDefaultEquals = {
val m = receiver.info.member(nme.equals_)
(m == Object_equals) || (m == Any_equals)
}
- // Whether this == or != is actually an overloaded version
+ // Whether this == or != is one of those defined in Any/AnyRef or an overload from elsewhere.
def isUsingDefaultScalaOp = {
val s = fn.symbol
- (s == Object_==) || (s == Object_!=) || (s == Any_==) || (s == Any_!=) || (s == Object_eq) || (s == Object_ne)
+ (s == Object_==) || (s == Object_!=) || (s == Any_==) || (s == Any_!=)
}
// Whether the operands+operator represent a warnable combo (assuming anyrefs)
- def isWarnable = isReferenceOp || (isUsingDefaultEquals && isUsingDefaultScalaOp)
- def isScalaNumber(s: Symbol) = isNumericValueClass(s) || (s isSubClass BoxedNumberClass) || (s isSubClass ScalaNumberClass)
- def isEitherNull = (receiver == NullClass) || (actual == NullClass)
- def isEitherNullable = (NullClass.tpe <:< receiver.info) || (NullClass.tpe <:< actual.info)
+ def isWarnable = isReferenceOp || (isUsingDefaultEquals && isUsingDefaultScalaOp)
+ def isEitherNull = (receiver == NullClass) || (actual == NullClass)
+ def isEitherNullable = (NullClass.tpe <:< receiver.info) || (NullClass.tpe <:< actual.info)
+ 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 nonSensibleWarning(what: String, alwaysEqual: Boolean) = {
val msg = alwaysEqual == (name == nme.EQ || name == nme.eq)
@@ -895,23 +900,37 @@ abstract class RefChecks extends InfoTransform {
}
// @MAT normalize for consistency in error message, otherwise only part is normalized due to use of `typeSymbol'
- def nonSensible(pre: String, alwaysEqual: Boolean) =
- nonSensibleWarning(pre+"values of types "+normalizeAll(qual.tpe.widen)+" and "+normalizeAll(args.head.tpe.widen),
- alwaysEqual)
-
- if (receiver == BooleanClass && !(receiver isSubClass actual)) // true == 5
- nonSensible("", false)
- else if (receiver == UnitClass && actual == UnitClass) // () == ()
- nonSensible("", true)
- else if (isNumericValueClass(receiver)) {
- if (!isScalaNumber(actual) && !forMSIL) // 5 == "abc"
+ def nonSensible(pre: String, alwaysEqual: Boolean) = nonSensibleWarning(
+ pre+"values of types "+normalizeAll(qual.tpe.widen)+" and "+normalizeAll(args.head.tpe.widen),
+ alwaysEqual
+ )
+
+ if (isBoolean(receiver)) {
+ if (!isBoolean(actual) && !isMaybeValue(actual)) // true == 5
+ nonSensible("", false)
+ }
+ else if (isUnit(receiver)) {
+ if (isUnit(actual)) // () == ()
+ nonSensible("", true)
+ else if (!isUnit(actual) && !isMaybeValue(actual)) // () == "abc"
nonSensible("", false)
}
+ else if (isNumeric(receiver)) {
+ if (!isNumeric(actual) && !forMSIL)
+ if (isUnit(actual) || isBoolean(actual) || !isMaybeValue(actual)) // 5 == "abc"
+ nonSensible("", false)
+ }
else if (isWarnable) {
- if (receiver.isFinal && !isEitherNull && !(receiver isSubClass actual)) // object X, Y; X == Y
- nonSensible((if (isEitherNullable) "non-null " else ""), false)
- else if (isNew(qual) || (isNew(args.head) && (receiver.isFinal || isReferenceOp))) // new X == y or object X ; X == new Y
+ if (isNew(qual)) // new X == y
+ nonSensibleWarning("a fresh object", false)
+ else if (isNew(args.head) && (receiver.isFinal || isReferenceOp)) // object X ; X == new Y
nonSensibleWarning("a fresh object", false)
+ else if (receiver.isFinal && !isEitherNull && !(receiver isSubClass actual)) { // object X, Y; X == Y
+ if (isEitherNullable)
+ nonSensible("non-null ", false)
+ else
+ nonSensible("", false)
+ }
}
case _ =>
}