Skip to content

Commit 1ec141e

Browse files
committed
Merge pull request #260 from dotty-staging/fix/method-impls
Make sure all non-deferred methods are implemented
2 parents 3ee4a25 + c16e4b2 commit 1ec141e

File tree

3 files changed

+44
-24
lines changed

3 files changed

+44
-24
lines changed

src/dotty/tools/dotc/transform/Memoize.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ import Decorators._
4343
*/
4444
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Mixin])
4545

46+
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
47+
case tree: DefDef if !tree.symbol.is(Lazy | Deferred) =>
48+
assert(!tree.rhs.isEmpty, i"unimplemented: $tree")
49+
case _ =>
50+
}
51+
4652
override def prepareForDefDef(tree: DefDef)(implicit ctx: Context) = {
4753
val sym = tree.symbol
4854
if (sym.isGetter && !sym.is(NoFieldNeeded)) {
@@ -74,13 +80,13 @@ import Decorators._
7480
Thicket(fieldDef, getterDef)
7581
}
7682
else if (sym.isSetter) {
77-
val Literal(Constant(())) = tree.rhs
83+
if (!sym.is(ParamAccessor)) { val Literal(Constant(())) = tree.rhs }
7884
val initializer = Assign(ref(field), ref(tree.vparamss.head.head.symbol))
7985
cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer))
8086
}
8187
else tree // curiously, some accessors from Scala2 have ' ' suffixes. They count as
8288
// neither getters nor setters
8389
else tree
8490
}
85-
private val NoFieldNeeded = Lazy | Deferred | ParamAccessor | JavaDefined
91+
private val NoFieldNeeded = Lazy | Deferred | JavaDefined
8692
}

src/dotty/tools/dotc/transform/ResolveSuper.scala

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,32 +50,32 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
5050

5151
override def treeTransformPhase = thisTransform.next
5252

53+
/** Returns the symbol that is accessed by a super-accessor in a mixin composition.
54+
*
55+
* @param base The class in which everything is mixed together
56+
* @param member The symbol statically referred to by the superaccessor in the trait
57+
*/
58+
private def rebindSuper(base: Symbol, acc: Symbol)(implicit ctx: Context): Symbol = {
59+
var bcs = base.info.baseClasses.dropWhile(acc.owner != _).tail
60+
var sym: Symbol = NoSymbol
61+
val SuperAccessorName(memberName) = acc.name: Name // dotty deviation: ": Name" needed otherwise pattern type is neither a subtype nor a supertype of selector type
62+
ctx.debuglog(i"starting rebindsuper from $base of ${acc.showLocated}: ${acc.info} in $bcs, name = $memberName")
63+
while (bcs.nonEmpty && sym == NoSymbol) {
64+
val other = bcs.head.info.nonPrivateDecl(memberName)
65+
if (ctx.settings.debug.value)
66+
ctx.log(i"rebindsuper ${bcs.head} $other deferred = ${other.symbol.is(Deferred)}")
67+
sym = other.matchingDenotation(base.thisType, base.thisType.memberInfo(acc)).symbol
68+
bcs = bcs.tail
69+
}
70+
assert(sym.exists)
71+
sym
72+
}
73+
5374
override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = {
5475
val cls = impl.symbol.owner.asClass
5576
val ops = new MixinOps(cls, thisTransform)
5677
import ops._
5778

58-
/** Returns the symbol that is accessed by a super-accessor in a mixin composition.
59-
*
60-
* @param base The class in which everything is mixed together
61-
* @param member The symbol statically referred to by the superaccessor in the trait
62-
*/
63-
def rebindSuper(base: Symbol, acc: Symbol): Symbol = {
64-
var bcs = cls.info.baseClasses.dropWhile(acc.owner != _).tail
65-
var sym: Symbol = NoSymbol
66-
val SuperAccessorName(memberName) = acc.name: Name // dotty deviation: ": Name" needed otherwise pattern type is neither a subtype nor a supertype of selector type
67-
ctx.debuglog(i"starting rebindsuper from $cls of ${acc.showLocated}: ${acc.info} in $bcs, name = $memberName")
68-
while (bcs.nonEmpty && sym == NoSymbol) {
69-
val other = bcs.head.info.nonPrivateDecl(memberName)
70-
if (ctx.settings.debug.value)
71-
ctx.log(i"rebindsuper ${bcs.head} $other deferred = ${other.symbol.is(Deferred)}")
72-
sym = other.matchingDenotation(cls.thisType, cls.thisType.memberInfo(acc)).symbol
73-
bcs = bcs.tail
74-
}
75-
assert(sym.exists)
76-
sym
77-
}
78-
7979
def superAccessors(mixin: ClassSymbol): List[Tree] =
8080
for (superAcc <- mixin.decls.filter(_ is SuperAccessor).toList)
8181
yield polyDefDef(implementation(superAcc.asTerm), forwarder(rebindSuper(cls, superAcc)))
@@ -94,5 +94,18 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
9494

9595
cpy.Template(impl)(body = overrides ::: impl.body)
9696
}
97+
98+
override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
99+
val meth = ddef.symbol.asTerm
100+
if (meth.is(SuperAccessor, butNot = Deferred)) {
101+
assert(ddef.rhs.isEmpty)
102+
val cls = meth.owner.asClass
103+
val ops = new MixinOps(cls, thisTransform)
104+
import ops._
105+
polyDefDef(meth, forwarder(rebindSuper(cls, meth)))
106+
}
107+
else ddef
108+
}
109+
97110
private val PrivateOrDeferred = Private | Deferred
98111
}

src/dotty/tools/dotc/transform/SuperAccessors.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ class SuperAccessors extends MacroTransform with IdentityDenotTransformer { this
8989

9090
val superAcc = clazz.info.decl(supername).suchThat(_.signature == sym.signature).symbol orElse {
9191
ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz")
92+
val maybeDeferred = if (clazz is Trait) Deferred else EmptyFlags
9293
val acc = ctx.newSymbol(
93-
clazz, supername, SuperAccessor | Private | Artifact | Method,
94+
clazz, supername, SuperAccessor | Private | Artifact | Method | maybeDeferred,
9495
ensureMethodic(sel.tpe.widenSingleton), coord = sym.coord).enteredAfter(thisTransformer)
9596
// Diagnostic for SI-7091
9697
if (!accDefs.contains(clazz))

0 commit comments

Comments
 (0)