@@ -115,15 +115,39 @@ class SuperAccessors(thisPhase: DenotTransformer) {
115
115
sel.sourcePos)
116
116
else ctx.log(i " ok super $sel ${sym.showLocated} $member $clazz ${member.isIncompleteIn(clazz)}" )
117
117
}
118
- else if (mix.name.isEmpty && ! (sym.owner is Trait ))
119
- // SI-4989 Check if an intermediate class between `clazz` and `sym.owner` redeclares the method as abstract.
120
- for (intermediateClass <- clazz.info.baseClasses.tail.takeWhile(_ != sym.owner)) {
121
- val overriding = sym.overridingSymbol(intermediateClass)
122
- if ((overriding is (Deferred , butNot = AbsOverride )) && ! (overriding.owner is Trait ))
123
- ctx.error(
124
- s " ${sym.showLocated} cannot be directly accessed from ${clazz} because ${overriding.owner} redeclares it as abstract " ,
118
+ else {
119
+ val owner = sym.owner
120
+ if (! owner.is(Trait )) {
121
+ if (mix.name.isEmpty) {
122
+ // scala/bug#4989 Check if an intermediate class between `clazz` and `sym.owner` redeclares the method as abstract.
123
+ for (intermediateClass <- clazz.info.baseClasses.tail.takeWhile(_ != sym.owner)) {
124
+ val overriding = sym.overridingSymbol(intermediateClass)
125
+ if ((overriding is (Deferred , butNot = AbsOverride )) && ! (overriding.owner is Trait ))
126
+ ctx.error(
127
+ s " ${sym.showLocated} cannot be directly accessed from ${clazz} because ${overriding.owner} redeclares it as abstract " ,
128
+ sel.sourcePos)
129
+ }
130
+ } else {
131
+ // scala/scala-dev#143:
132
+ // a call `super[T].m` that resolves to `A.m` cannot be translated to correct bytecode if
133
+ // `A` is a class (not a trait / interface), but not the direct superclass. Invokespecial
134
+ // would select an overriding method in the direct superclass, rather than `A.m`.
135
+ // We allow this if there are statically no intervening overrides.
136
+ def hasClassOverride (member : Symbol , subCls : ClassSymbol ): Boolean = {
137
+ if (subCls == defn.ObjectClass || subCls == member.owner) false
138
+ else if (member.overridingSymbol(subCls).exists) true
139
+ else hasClassOverride(member, subCls.superClass.asClass)
140
+ }
141
+ val superCls = clazz.asClass.superClass.asClass
142
+ if (owner != superCls && hasClassOverride(sym, superCls)) {
143
+ ctx.error(
144
+ hl """ Super call cannot be emitted: the selected $sym is declared in $owner, which is not the direct superclass of $clazz.
145
+ |An unqualified super call (super. ${sym.name}) would be allowed. """ ,
125
146
sel.sourcePos)
147
+ }
148
+ }
126
149
}
150
+ }
127
151
if (name.isTermName && mix.name.isEmpty &&
128
152
((clazz is Trait ) || clazz != ctx.owner.enclosingClass || ! validCurrentClass))
129
153
superAccessorCall(sel)(ctx.withPhase(thisPhase.next))
0 commit comments