diff options
author | Paul Phillips <paulp@improving.org> | 2013-02-19 12:57:21 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-02-19 13:07:55 -0800 |
commit | 0eff6cd49d32c20d5648b57a01b5e80339a1cca7 (patch) | |
tree | 44e41e47efafccc9ccd343e97de69e486e972104 /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | |
parent | bafebe1c161f8db0be758c30fe5cc51082a56427 (diff) | |
download | scala-0eff6cd49d32c20d5648b57a01b5e80339a1cca7.tar.gz scala-0eff6cd49d32c20d5648b57a01b5e80339a1cca7.tar.bz2 scala-0eff6cd49d32c20d5648b57a01b5e80339a1cca7.zip |
Fix and optimization in overriding logic.
Given:
trait Foo { def f: Int = 5 }
trait Bar extends Foo { def f: Int }
I noticed allOverriddenSymbols for the abstract f defined in Bar
was returning the method from Foo, even though an abstract method
cannot override a concrete one. There were other bits of code
which accidentally depended on this outcome. Now allOverriddenSymbols
for Bar is empty.
The optimization is that whether or not a symbol overrides
any other symbols is known at creation time and does not change.
We now spend a lot less time looking for overridden symbols in
base classes by storing that value, "isOverridingSymbol".
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 60a73036f8..dd16e9de30 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -726,8 +726,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans else if (clazz.isTrait && !(clazz isSubClass AnyValClass)) { // For non-AnyVal classes, prevent abstract methods in interfaces that override // final members in Object; see #4431 - for (decl <- clazz.info.decls.iterator) { - val overridden = decl.overriddenSymbol(ObjectClass) + for (decl <- clazz.info.decls) { + // Have to use matchingSymbol, not a method involving overridden symbols, + // because the scala type system understands that an abstract method here does not + // override a concrete method in Object. The jvm, however, does not. + val overridden = decl.matchingSymbol(ObjectClass, ObjectClass.tpe) if (overridden.isFinal) unit.error(decl.pos, "trait cannot redefine final method from class AnyRef") } @@ -1499,8 +1502,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // on Unit, in which case we had better let it slide. val isOk = ( sym.isGetter - || sym.allOverriddenSymbols.exists(over => !(over.tpe.resultType =:= sym.tpe.resultType)) || (sym.name containsName nme.DEFAULT_GETTER_STRING) + || sym.allOverriddenSymbols.exists(over => !(over.tpe.resultType =:= sym.tpe.resultType)) ) if (!isOk) unit.warning(sym.pos, s"side-effecting nullary methods are discouraged: suggest defining as `def ${sym.name.decode}()` instead") |