diff --git a/src/dotty/tools/dotc/transform/Memoize.scala b/src/dotty/tools/dotc/transform/Memoize.scala index f4b00d6a5e86..17a84484a115 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 23ff45a7c0b1..6b1b55b0a73f 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 8a531de8d835..f727201b2895 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))