diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-09-05 09:55:04 +1000 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2016-09-05 22:47:47 +0200 |
commit | 0a840380aa47d52d2addd2b96dbbb68b874c3a67 (patch) | |
tree | 04052ca7a13877ed8d38a3b84960567a0f8d7cef /src/compiler/scala/tools/nsc/typechecker | |
parent | d29df860e5b10181f6c37bde3bd7539bdc843e0d (diff) | |
download | scala-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.scala | 8 |
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.") |