summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-02-01 08:06:24 -0800
committerPaul Phillips <paulp@improving.org>2012-02-01 09:32:52 -0800
commitf55db64983edfeb9484b7617e2b59f8994c37ef3 (patch)
tree82625ed61088f1a2230790008ab9aa6a08d39e51 /src/compiler
parent37bcff7956451cd74d08899e0e49c8b569d3a882 (diff)
downloadscala-f55db64983edfeb9484b7617e2b59f8994c37ef3.tar.gz
scala-f55db64983edfeb9484b7617e2b59f8994c37ef3.tar.bz2
scala-f55db64983edfeb9484b7617e2b59f8994c37ef3.zip
Fix for bad bug with accidental overrides.
An object in a subclass would silently override an inherited method, then throw a CCE at runtime. I blamed this on matchesType and altered it accordingly. There's a pretty extensive test case which reflects my expectations. Review by @odersky please. Closes SI-5429.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
3 files changed, 20 insertions, 2 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 371fb8d585..c8b960ebe8 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -5477,6 +5477,8 @@ trait Types extends api.Types { self: SymbolTable =>
else matchesType(tp1, res2, alwaysMatchSimple)
case ExistentialType(_, res2) =>
alwaysMatchSimple && matchesType(tp1, res2, true)
+ case TypeRef(_, sym, Nil) =>
+ params1.isEmpty && sym.isModuleClass && matchesType(res1, sym.tpe, alwaysMatchSimple)
case _ =>
false
}
@@ -5488,6 +5490,8 @@ trait Types extends api.Types { self: SymbolTable =>
matchesType(res1, res2, alwaysMatchSimple)
case ExistentialType(_, res2) =>
alwaysMatchSimple && matchesType(tp1, res2, true)
+ case TypeRef(_, sym, Nil) if sym.isModuleClass =>
+ matchesType(res1, sym.tpe, alwaysMatchSimple)
case _ =>
matchesType(res1, tp2, alwaysMatchSimple)
}
@@ -5508,6 +5512,12 @@ trait Types extends api.Types { self: SymbolTable =>
if (alwaysMatchSimple) matchesType(res1, tp2, true)
else lastTry
}
+ case TypeRef(_, sym, Nil) if sym.isModuleClass =>
+ tp2 match {
+ case MethodType(Nil, res2) => matchesType(sym.tpe, res2, alwaysMatchSimple)
+ case NullaryMethodType(res2) => matchesType(sym.tpe, res2, alwaysMatchSimple)
+ case _ => lastTry
+ }
case _ =>
lastTry
}
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index 1200e973c5..e49f8d7c0b 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -45,8 +45,14 @@ abstract class OverridingPairs {
* Types always match. Term symbols match if their membertypes
* relative to <base>.this do
*/
- protected def matches(sym1: Symbol, sym2: Symbol): Boolean =
- sym1.isType || (self.memberType(sym1) matches self.memberType(sym2))
+ protected def matches(sym1: Symbol, sym2: Symbol): Boolean = {
+ def tp_s(s: Symbol) = self.memberType(s) + "/" + self.memberType(s).getClass
+ val result = sym1.isType || (self.memberType(sym1) matches self.memberType(sym2))
+ debuglog("overriding-pairs? %s matches %s (%s vs. %s) == %s".format(
+ sym1.fullLocationString, sym2.fullLocationString, tp_s(sym1), tp_s(sym2), result))
+
+ result
+ }
/** An implementation of BitSets as arrays (maybe consider collection.BitSet
* for that?) The main purpose of this is to implement
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index a6c2f75d5e..5aa1843188 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -276,6 +276,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
* of class `clazz` are met.
*/
def checkOverride(member: Symbol, other: Symbol) {
+ debuglog("Checking validity of %s overriding %s".format(member.fullLocationString, other.fullLocationString))
+
def memberTp = self.memberType(member)
def otherTp = self.memberType(other)
def noErrorType = other.tpe != ErrorType && member.tpe != ErrorType