aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/ResolveSuper.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-08 09:45:30 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-09 19:09:52 +0100
commitfea26e104d202f3ac755f309d982af4d7ddd7bba (patch)
treea921ae55d84c587784ddeb0bad7780e823ff68fc /src/dotty/tools/dotc/transform/ResolveSuper.scala
parent0cd63ac2a8ae378d85922cbef4c3b4654fb75ea7 (diff)
downloaddotty-fea26e104d202f3ac755f309d982af4d7ddd7bba.tar.gz
dotty-fea26e104d202f3ac755f309d982af4d7ddd7bba.tar.bz2
dotty-fea26e104d202f3ac755f309d982af4d7ddd7bba.zip
New Mixin scheme.
Split into two phases, ResolveSuper before Erasure and Mixin after. Likewise GettersSetters is split into Getters and Memoize. All tests pass, except two tests fail when compiled twice. Will investigate next why.
Diffstat (limited to 'src/dotty/tools/dotc/transform/ResolveSuper.scala')
-rw-r--r--src/dotty/tools/dotc/transform/ResolveSuper.scala95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/transform/ResolveSuper.scala b/src/dotty/tools/dotc/transform/ResolveSuper.scala
new file mode 100644
index 000000000..1fd8b122f
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/ResolveSuper.scala
@@ -0,0 +1,95 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import TreeTransforms._
+import Contexts.Context
+import Flags._
+import SymUtils._
+import Symbols._
+import SymDenotations._
+import Types._
+import Decorators._
+import DenotTransformers._
+import StdNames._
+import NameOps._
+import ast.Trees._
+import util.Positions._
+import Names._
+import collection.mutable
+
+/** This phase adds super accessors and method overrides where
+ * linearization differs from Java's rule for default methods in interfaces.
+ * In particular:
+ *
+ * For every trait M directly implemented by the class (see SymUtils.mixin), in
+ * reverse linearization order, add the following definitions to C:
+ *
+ * 3.1 (done in `superAccessors`) For every superAccessor
+ * `<mods> def super$f[Ts](ps1)...(psN): U` in M:
+ *
+ * <mods> def super$f[Ts](ps1)...(psN): U = super[S].f[Ts](ps1)...(psN)
+ *
+ * where `S` is the superclass of `M` in the linearization of `C`.
+ *
+ * 3.2 (done in `methodOverrides`) For every method
+ * `<mods> def f[Ts](ps1)...(psN): U` in M` that needs to be disambiguated:
+ *
+ * <mods> def f[Ts](ps1)...(psN): U = super[M].f[Ts](ps1)...(psN)
+ *
+ * A method in M needs to be disambiguated if it is concrete, not overridden in C,
+ * and if it overrides another concrete method.
+ */
+class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
+ import ast.tpd._
+
+ override def phaseName: String = "resolveSuper"
+
+ override def treeTransformPhase = thisTransform.next
+
+ 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
+ println(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)
+ println(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)))
+
+ def methodOverrides(mixin: ClassSymbol): List[Tree] = {
+ def isOverridden(meth: Symbol) = meth.overridingSymbol(cls).is(Method, butNot = Deferred)
+ def needsDisambiguation(meth: Symbol): Boolean =
+ meth.is(Method, butNot = PrivateOrDeferred) &&
+ !isOverridden(meth) &&
+ !meth.allOverriddenSymbols.forall(_ is Deferred)
+ for (meth <- mixin.decls.toList if needsDisambiguation(meth))
+ yield polyDefDef(implementation(meth.asTerm), forwarder(meth))
+ }
+
+ val overrides = mixins.flatMap(mixin => superAccessors(mixin) ::: methodOverrides(mixin))
+
+ cpy.Template(impl)(body = overrides ::: impl.body)
+ }
+ private val PrivateOrDeferred = Private | Deferred
+}