diff options
author | Paul Phillips <paulp@improving.org> | 2012-02-01 08:06:24 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-02-01 09:32:52 -0800 |
commit | f55db64983edfeb9484b7617e2b59f8994c37ef3 (patch) | |
tree | 82625ed61088f1a2230790008ab9aa6a08d39e51 /src/compiler | |
parent | 37bcff7956451cd74d08899e0e49c8b569d3a882 (diff) | |
download | scala-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')
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 |