summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-09-05 09:55:04 +1000
committerLukas Rytz <lukas.rytz@gmail.com>2016-09-05 22:47:47 +0200
commit0a840380aa47d52d2addd2b96dbbb68b874c3a67 (patch)
tree04052ca7a13877ed8d38a3b84960567a0f8d7cef /src/compiler/scala/tools/nsc/typechecker
parentd29df860e5b10181f6c37bde3bd7539bdc843e0d (diff)
downloadscala-0a840380aa47d52d2addd2b96dbbb68b874c3a67.tar.gz
scala-0a840380aa47d52d2addd2b96dbbb68b874c3a67.tar.bz2
scala-0a840380aa47d52d2addd2b96dbbb68b874c3a67.zip
SD-143 allow super calls to methods defined in indirect super classes
The restriction for super calls to methods defined in indirect super classes introduced in a980fde was over-restrictive. In particular, it ruled out a valid code pattern to select a method from a superclass when an unqualified `super` would resolve to an override defined in a trait (example in the commit as a test).
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala8
1 files changed, 7 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index a38d21fe10..963a9dea02 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -152,11 +152,17 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
// SD-143: a call super[T].m that resolves to A.m cannot be translated to correct bytecode if
// - A is a class (not a trait / interface), but not the direct superclass. Invokespecial
// would select an overriding method in the direct superclass, rather than A.m.
+ // We allow this if there are statically no intervening overrides.
// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokespecial
// - A is a java-defined interface and not listed as direct parent of the class. In this
// case, `invokespecial A.m` would be invalid.
+ def hasClassOverride(member: Symbol, subclass: Symbol): Boolean = {
+ if (subclass == ObjectClass || subclass == member.owner) false
+ else if (member.overridingSymbol(subclass) != NoSymbol) true
+ else hasClassOverride(member, subclass.superClass)
+ }
val owner = sym.owner
- if (!owner.isTrait && owner != clazz.superClass) {
+ if (!owner.isTrait && owner != clazz.superClass && hasClassOverride(sym, clazz.superClass)) {
reporter.error(sel.pos,
s"cannot emit super call: the selected $sym is declared in $owner, which is not the direct superclass of $clazz.\n" +
s"An unqualified super call (super.${sym.name}) would be allowed.")