aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2015-08-28 17:01:39 +0200
committerDmitry Petrashko <dark@d-d.me>2015-08-28 17:01:39 +0200
commitfbc1609b6022513168996cf126f7b32105312849 (patch)
tree5cd07f7d6bf2da7f6da277d4730e40dea7019e45
parent6ccd6b5f95ed6c6e042cc79f97dc08e1c50ac438 (diff)
parent4689bd39e3c5271333bb6dec1370b4e5c802f7e0 (diff)
downloaddotty-fbc1609b6022513168996cf126f7b32105312849.tar.gz
dotty-fbc1609b6022513168996cf126f7b32105312849.tar.bz2
dotty-fbc1609b6022513168996cf126f7b32105312849.zip
Merge pull request #767 from dotty-staging/fix-#756-super-accessors
Fix #756 super accessors
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala5
-rw-r--r--src/dotty/tools/dotc/transform/ResolveSuper.scala8
-rw-r--r--src/dotty/tools/dotc/transform/SuperAccessors.scala8
-rw-r--r--test/dotc/tests.scala1
-rw-r--r--tests/neg/abstract-override.scala8
-rw-r--r--tests/run/i756.scala8
6 files changed, 34 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index 593d5f036..cab47025e 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -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]
diff --git a/src/dotty/tools/dotc/transform/ResolveSuper.scala b/src/dotty/tools/dotc/transform/ResolveSuper.scala
index 2e1409723..26128cf33 100644
--- a/src/dotty/tools/dotc/transform/ResolveSuper.scala
+++ b/src/dotty/tools/dotc/transform/ResolveSuper.scala
@@ -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)
diff --git a/src/dotty/tools/dotc/transform/SuperAccessors.scala b/src/dotty/tools/dotc/transform/SuperAccessors.scala
index 23201a978..31cfef914 100644
--- a/src/dotty/tools/dotc/transform/SuperAccessors.scala
+++ b/src/dotty/tools/dotc/transform/SuperAccessors.scala
@@ -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)
@@ -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.
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index b5af92d64..0838874c9 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -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)
@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)
diff --git a/tests/neg/abstract-override.scala b/tests/neg/abstract-override.scala
new file mode 100644
index 000000000..c1ce83725
--- /dev/null
+++ b/tests/neg/abstract-override.scala
@@ -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)
+ }
+}
diff --git a/tests/run/i756.scala b/tests/run/i756.scala
new file mode 100644
index 000000000..dd9b2be4f
--- /dev/null
+++ b/tests/run/i756.scala
@@ -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)
+ }
+}