diff options
author | Felix Mulder <felix.mulder@gmail.com> | 2016-11-02 11:08:28 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-11-22 01:35:07 +0100 |
commit | 8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch) | |
tree | a8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala | |
parent | 6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff) | |
download | dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2 dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip |
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala new file mode 100644 index 000000000..e718a7e60 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala @@ -0,0 +1,115 @@ +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 +import ResolveSuper._ + +/** 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. + * + * This is the first part of what was the mixin phase. It is complemented by + * Mixin, which runs after erasure. + */ +class ResolveSuper extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => + import ast.tpd._ + + override def phaseName: String = "resolveSuper" + + override def runsAfter = Set(classOf[ElimByName], // verified empirically, need to figure out what the reason is. + classOf[AugmentScala2Traits]) + + override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = { + val cls = impl.symbol.owner.asClass + val ops = new MixinOps(cls, thisTransform) + import ops._ + + def superAccessors(mixin: ClassSymbol): List[Tree] = + for (superAcc <- mixin.info.decls.filter(_ is SuperAccessor).toList) + yield polyDefDef(implementation(superAcc.asTerm), forwarder(rebindSuper(cls, superAcc))) + + def methodOverrides(mixin: ClassSymbol): List[Tree] = + for (meth <- mixin.info.decls.toList if needsForwarder(meth)) + yield polyDefDef(implementation(meth.asTerm), forwarder(meth)) + + val overrides = mixins.flatMap(mixin => superAccessors(mixin) ::: methodOverrides(mixin)) + + 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 PrivateOrAccessorOrDeferred = Private | Accessor | Deferred +} + +object ResolveSuper{ + /** 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 acc The symbol statically referred to by the superaccessor in the trait + */ + def rebindSuper(base: Symbol, acc: Symbol)(implicit ctx: Context): Symbol = { + var bcs = base.info.baseClasses.dropWhile(acc.owner != _).tail + var sym: Symbol = NoSymbol + val unexpandedAccName = + if (acc.is(ExpandedName)) // Cannot use unexpandedName because of #765. t2183.scala would fail if we did. + acc.name + .drop(acc.name.indexOfSlice(nme.EXPAND_SEPARATOR ++ nme.SUPER_PREFIX)) + .drop(nme.EXPAND_SEPARATOR.length) + else acc.name + val SuperAccessorName(memberName) = unexpandedAccName: 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 + } +} |