aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-12-03 14:46:40 +0100
committerMartin Odersky <odersky@gmail.com>2014-12-03 14:46:40 +0100
commitc16e4b2bd8948be3a250373fb9eac98bb990e43a (patch)
treeefc8cb734a2b017fe4ae9a19845094e27b52daca /src
parent5ff3d0fe4370c525c8d29f6483892d0bf59cd4c0 (diff)
downloaddotty-c16e4b2bd8948be3a250373fb9eac98bb990e43a.tar.gz
dotty-c16e4b2bd8948be3a250373fb9eac98bb990e43a.tar.bz2
dotty-c16e4b2bd8948be3a250373fb9eac98bb990e43a.zip
Make sure all non-deferred methods are implemented
Checked by a new post condition after memoize. Two bugs were detected and fixed by the condition (1) Memoize did not implement getters and setters of ParamAccessors (2) ResolveSuper did not implement super accessors in non-trait classes.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/transform/Memoize.scala10
-rw-r--r--src/dotty/tools/dotc/transform/ResolveSuper.scala55
-rw-r--r--src/dotty/tools/dotc/transform/SuperAccessors.scala3
3 files changed, 44 insertions, 24 deletions
diff --git a/src/dotty/tools/dotc/transform/Memoize.scala b/src/dotty/tools/dotc/transform/Memoize.scala
index f4b00d6a5..17a84484a 100644
--- a/src/dotty/tools/dotc/transform/Memoize.scala
+++ b/src/dotty/tools/dotc/transform/Memoize.scala
@@ -43,6 +43,12 @@ import Decorators._
*/
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Mixin])
+ override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
+ case tree: DefDef if !tree.symbol.is(Lazy | Deferred) =>
+ assert(!tree.rhs.isEmpty, i"unimplemented: $tree")
+ case _ =>
+ }
+
override def prepareForDefDef(tree: DefDef)(implicit ctx: Context) = {
val sym = tree.symbol
if (sym.isGetter && !sym.is(NoFieldNeeded)) {
@@ -74,7 +80,7 @@ import Decorators._
Thicket(fieldDef, getterDef)
}
else if (sym.isSetter) {
- val Literal(Constant(())) = tree.rhs
+ if (!sym.is(ParamAccessor)) { val Literal(Constant(())) = tree.rhs }
val initializer = Assign(ref(field), ref(tree.vparamss.head.head.symbol))
cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer))
}
@@ -82,5 +88,5 @@ import Decorators._
// neither getters nor setters
else tree
}
- private val NoFieldNeeded = Lazy | Deferred | ParamAccessor | JavaDefined
+ private val NoFieldNeeded = Lazy | Deferred | JavaDefined
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/transform/ResolveSuper.scala b/src/dotty/tools/dotc/transform/ResolveSuper.scala
index 23ff45a7c..6b1b55b0a 100644
--- a/src/dotty/tools/dotc/transform/ResolveSuper.scala
+++ b/src/dotty/tools/dotc/transform/ResolveSuper.scala
@@ -50,32 +50,32 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
override def treeTransformPhase = thisTransform.next
+ /** Returns the symbol that is accessed by a super-accessor in a mixin composition.
+ *
+ * @param base The class in which everything is mixed together
+ * @param member The symbol statically referred to by the superaccessor in the trait
+ */
+ 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) = acc.name: 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)
+ if (ctx.settings.debug.value)
+ ctx.log(i"rebindsuper ${bcs.head} $other deferred = ${other.symbol.is(Deferred)}")
+ sym = other.matchingDenotation(base.thisType, base.thisType.memberInfo(acc)).symbol
+ bcs = bcs.tail
+ }
+ assert(sym.exists)
+ sym
+ }
+
override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = {
val cls = impl.symbol.owner.asClass
val ops = new MixinOps(cls, thisTransform)
import ops._
- /** Returns the symbol that is accessed by a super-accessor in a mixin composition.
- *
- * @param base The class in which everything is mixed together
- * @param member The symbol statically referred to by the superaccessor in the trait
- */
- def rebindSuper(base: Symbol, acc: Symbol): Symbol = {
- var bcs = cls.info.baseClasses.dropWhile(acc.owner != _).tail
- var sym: Symbol = NoSymbol
- val SuperAccessorName(memberName) = acc.name: Name // dotty deviation: ": Name" needed otherwise pattern type is neither a subtype nor a supertype of selector type
- ctx.debuglog(i"starting rebindsuper from $cls of ${acc.showLocated}: ${acc.info} in $bcs, name = $memberName")
- while (bcs.nonEmpty && sym == NoSymbol) {
- val other = bcs.head.info.nonPrivateDecl(memberName)
- if (ctx.settings.debug.value)
- ctx.log(i"rebindsuper ${bcs.head} $other deferred = ${other.symbol.is(Deferred)}")
- sym = other.matchingDenotation(cls.thisType, cls.thisType.memberInfo(acc)).symbol
- bcs = bcs.tail
- }
- assert(sym.exists)
- sym
- }
-
def superAccessors(mixin: ClassSymbol): List[Tree] =
for (superAcc <- mixin.decls.filter(_ is SuperAccessor).toList)
yield polyDefDef(implementation(superAcc.asTerm), forwarder(rebindSuper(cls, superAcc)))
@@ -94,5 +94,18 @@ class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { th
cpy.Template(impl)(body = overrides ::: impl.body)
}
+
+ override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
+ val meth = ddef.symbol.asTerm
+ if (meth.is(SuperAccessor, butNot = Deferred)) {
+ assert(ddef.rhs.isEmpty)
+ val cls = meth.owner.asClass
+ val ops = new MixinOps(cls, thisTransform)
+ import ops._
+ polyDefDef(meth, forwarder(rebindSuper(cls, meth)))
+ }
+ else ddef
+ }
+
private val PrivateOrDeferred = Private | Deferred
}
diff --git a/src/dotty/tools/dotc/transform/SuperAccessors.scala b/src/dotty/tools/dotc/transform/SuperAccessors.scala
index 8a531de8d..f727201b2 100644
--- a/src/dotty/tools/dotc/transform/SuperAccessors.scala
+++ b/src/dotty/tools/dotc/transform/SuperAccessors.scala
@@ -89,8 +89,9 @@ class SuperAccessors extends MacroTransform with IdentityDenotTransformer { this
val superAcc = clazz.info.decl(supername).suchThat(_.signature == sym.signature).symbol orElse {
ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz")
+ val maybeDeferred = if (clazz is Trait) Deferred else EmptyFlags
val acc = ctx.newSymbol(
- clazz, supername, SuperAccessor | Private | Artifact | Method,
+ clazz, supername, SuperAccessor | Private | Artifact | Method | maybeDeferred,
ensureMethodic(sel.tpe.widenSingleton), coord = sym.coord).enteredAfter(thisTransformer)
// Diagnostic for SI-7091
if (!accDefs.contains(clazz))