Skip to content

Fix #756 super accessors #767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ object NameOps {

def expandedName(prefix: Name): N = expandedName(prefix, nme.EXPAND_SEPARATOR)

/** Revert the expanded name. Note: This currently gives incorrect results
* if the normal name contains `nme.EXPAND_SEPARATOR`, i.e. two consecutive '$'
* signs. This can happen for instance if a super accessor is paired with
* an encoded name, e.g. super$$plus$eq. See #765.
*/
def unexpandedName: N = {
val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length)).asInstanceOf[N]
Expand Down
8 changes: 7 additions & 1 deletion src/dotty/tools/dotc/transform/ResolveSuper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
private def rebindSuper(base: Symbol, acc: Symbol)(implicit ctx: Context): Symbol = {
var bcs = base.info.baseClasses.dropWhile(acc.owner != _).tail
var sym: Symbol = NoSymbol
val SuperAccessorName(memberName) = ctx.atPhase(ctx.picklerPhase){ implicit ctx => acc.name }: Name // dotty deviation: ": Name" needed otherwise pattern type is neither a subtype nor a supertype of selector type
val unexpandedAccName =
if (acc.is(ExpandedName)) // Cannot use unexpandedName because of #765. t2183.scala would fail if we did.
acc.name
.drop(acc.name.indexOfSlice(nme.EXPAND_SEPARATOR ++ nme.SUPER_PREFIX))
.drop(nme.EXPAND_SEPARATOR.length)
else acc.name
val SuperAccessorName(memberName) = unexpandedAccName: Name // dotty deviation: ": Name" needed otherwise pattern type is neither a subtype nor a supertype of selector type
ctx.debuglog(i"starting rebindsuper from $base of ${acc.showLocated}: ${acc.info} in $bcs, name = $memberName")
while (bcs.nonEmpty && sym == NoSymbol) {
val other = bcs.head.info.nonPrivateDecl(memberName)
Expand Down
8 changes: 5 additions & 3 deletions src/dotty/tools/dotc/transform/SuperAccessors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
val Select(qual, name) = sel
val sym = sel.symbol
val clazz = qual.symbol.asClass
val supername = name.superName
var supername = name.superName
if (clazz is Trait) supername = supername.expandedName(clazz)

val superAcc = clazz.info.decl(supername).suchThat(_.signature == sym.signature).symbol orElse {
ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz")
val deferredOrPrivate = if (clazz is Trait) Deferred else Private
val deferredOrPrivate = if (clazz is Trait) Deferred | ExpandedName else Private
val acc = ctx.newSymbol(
clazz, supername, SuperAccessor | Artifact | Method | deferredOrPrivate,
sel.tpe.widenSingleton.ensureMethodic, coord = sym.coord).enteredAfter(thisTransformer)
Expand Down Expand Up @@ -106,10 +107,11 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
val member = sym.overridingSymbol(clazz)
if (mix != tpnme.EMPTY ||
!member.exists ||
!(member is AbsOverride) && member.isIncompleteIn(clazz))
!((member is AbsOverride) && member.isIncompleteIn(clazz)))
ctx.error(
i"${sym.showLocated} is accessed from super. It may not be abstract unless it is overridden by a member declared `abstract' and `override'",
sel.pos)
else println(i"ok super $sel ${sym.showLocated} $member $clazz ${member.isIncompleteIn(clazz)}")
}
else if (mix == tpnme.EMPTY && !(sym.owner is Trait))
// SI-4989 Check if an intermediate class between `clazz` and `sym.owner` redeclares the method as abstract.
Expand Down
1 change: 1 addition & 0 deletions test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class tests extends CompilerTest {

@Test def new_all = compileFiles(newDir, twice)

@Test def neg_abstractOverride() = compileFile(negDir, "abstract-override", xerrors = 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abstract-override.scala is absent in this PR.

@Test def neg_blockescapes() = compileFile(negDir, "blockescapesNeg", xerrors = 1)
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
@Test def neg_typedidents() = compileFile(negDir, "typedIdents", xerrors = 2)
Expand Down
8 changes: 8 additions & 0 deletions tests/neg/abstract-override.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
trait T { def foo: Int }
trait T1 extends T { override def foo = super.foo }
trait T2 extends T { override def foo = super.foo }
object Test extends T2 with T1 {
def main(args: Array[String]) = {
assert(foo == 3)
}
}
8 changes: 8 additions & 0 deletions tests/run/i756.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
trait T { def foo: Int = 3 }
trait T1 extends T { override def foo = super.foo }
trait T2 extends T { override def foo = super.foo }
object Test extends T2 with T1 {
def main(args: Array[String]) = {
assert(foo == 3)
}
}