diff options
author | Martin Odersky <odersky@gmail.com> | 2014-11-08 09:45:30 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-11-09 19:09:52 +0100 |
commit | fea26e104d202f3ac755f309d982af4d7ddd7bba (patch) | |
tree | a921ae55d84c587784ddeb0bad7780e823ff68fc /src/dotty/tools/dotc/transform/ResolveSuper.scala | |
parent | 0cd63ac2a8ae378d85922cbef4c3b4654fb75ea7 (diff) | |
download | dotty-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.scala | 95 |
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 +} |