summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/AddInterfaces.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala376
1 files changed, 0 insertions, 376 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
deleted file mode 100644
index 82e7c76409..0000000000
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ /dev/null
@@ -1,376 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package transform
-
-import symtab._
-import Flags._
-import scala.tools.nsc.util.ClassPath
-
-abstract class AddInterfaces extends InfoTransform { self: Erasure =>
- import global._ // the global environment
- import definitions._ // standard classes and methods
-
- /** The phase sets lateINTERFACE for non-interface traits that now
- * become interfaces. It sets lateDEFERRED for formerly concrete
- * methods in such traits.
- */
- override def phaseNewFlags: Long = lateDEFERRED | lateINTERFACE
-
- /** A lazily constructed map that associates every non-interface trait with
- * its implementation class.
- */
- private val implClassMap = perRunCaches.newMap[Symbol, Symbol]()
-
- /** A lazily constructed map that associates every concrete method in a non-interface
- * trait that's currently compiled with its corresponding method in the trait's
- * implementation class.
- */
- private val implMethodMap = perRunCaches.newMap[Symbol, Symbol]()
-
- override def newPhase(prev: scala.tools.nsc.Phase): StdPhase = {
- implClassMap.clear()
- implMethodMap.clear()
- super.newPhase(prev)
- }
-
- /** Is given trait member symbol a member of the trait's interface
- * after this transform is performed?
- */
- private def isInterfaceMember(sym: Symbol) = (
- sym.isType || {
- sym.info // initialize to set lateMETHOD flag if necessary
-
- ( sym.isMethod
- && !sym.isLabel
- && !sym.isPrivate
- && (!(sym hasFlag BRIDGE) || sym.hasBridgeAnnotation) // count @bridge annotated classes as interface members
- && !sym.isConstructor
- && !sym.isImplOnly
- )
- }
- )
-
- /** Does symbol need an implementation method? */
- def needsImplMethod(sym: Symbol) = (
- sym.isMethod
- && isInterfaceMember(sym)
- && (!sym.hasFlag(DEFERRED | SUPERACCESSOR) || (sym hasFlag lateDEFERRED))
- )
-
- def implClassPhase = currentRun.erasurePhase.next
-
- private def newImplClass(iface: Symbol): Symbol = {
- val inClass = iface.owner.isClass
- val implName = tpnme.implClassName(iface.name)
- val implFlags = (iface.flags & ~(INTERFACE | lateINTERFACE)) | IMPLCLASS
-
- val impl0 = {
- if (!inClass) NoSymbol
- else {
- val typeInfo = iface.owner.info
- typeInfo.decl(implName) match {
- case NoSymbol => NoSymbol
- case implSym =>
- // Unlink a pre-existing symbol only if the implementation class is
- // visible on the compilation classpath. In general this is true under
- // -optimise and not otherwise, but the classpath can use arbitrary
- // logic so the classpath must be queried.
- // TODO this is not taken into account by flat classpath yet
- classPath match {
- case cp: ClassPath[_] if !cp.context.isValidName(implName + ".class") =>
- log(s"not unlinking $iface's existing implClass ${implSym.name} because it is not on the classpath.")
- implSym
- case _ =>
- typeInfo.decls unlink implSym
- NoSymbol
- }
- }
- }
- }
-
- val impl = impl0 orElse {
- val impl = iface.owner.newImplClass(implName, iface.pos, implFlags)
- if (iface.thisSym != iface) {
- impl.typeOfThis = iface.typeOfThis
- impl.thisSym setName iface.thisSym.name
- }
- impl.associatedFile = iface.sourceFile
- if (inClass)
- iface.owner.info.decls enter impl
-
- impl
- }
- if (currentRun compiles iface)
- currentRun.symSource(impl) = iface.sourceFile
-
- implClassMap(iface) = impl
- impl setInfo new LazyImplClassType(iface)
- }
-
- /** Return the implementation class of a trait; create a new one if one does not yet exist */
- def implClass(iface: Symbol): Symbol = {
- iface.info
-
- implClassMap.getOrElse(iface, enteringPhase(implClassPhase) {
- if (iface.implClass eq NoSymbol)
- debuglog(s"${iface.fullLocationString} has no implClass yet, creating it now.")
- else
- log(s"${iface.fullLocationString} impl class is ${iface.implClass.nameString}")
-
- newImplClass(iface)
- })
- }
-
- /** A lazy type to set the info of an implementation class
- * The parents of an implementation class for trait iface are:
- *
- * - superclass: Object
- * - mixin classes: mixin classes of iface where every non-interface
- * trait is mapped to its implementation class, followed by iface itself.
- *
- * The declarations of a mixin class are:
- * - for every interface member of iface: its implementation method, if one is needed
- * - every former member of iface that is implementation only
- */
- private class LazyImplClassType(iface: Symbol) extends LazyType with FlagAgnosticCompleter {
- /** Compute the decls of implementation class implClass,
- * given the decls ifaceDecls of its interface.
- */
- private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {
- debuglog("LazyImplClassType calculating decls for " + implClass)
-
- val decls = newScope
- if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol) {
- log("Adding mixin constructor to " + implClass)
-
- decls enter (
- implClass.newMethod(nme.MIXIN_CONSTRUCTOR, implClass.pos)
- setInfo MethodType(Nil, UnitTpe)
- )
- }
-
- for (sym <- ifaceDecls) {
- if (isInterfaceMember(sym)) {
- if (needsImplMethod(sym)) {
- val clone = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED)
- if (currentRun.compiles(implClass)) implMethodMap(sym) = clone
- decls enter clone
- sym setFlag lateDEFERRED
- if (!sym.isSpecialized)
- log(s"Cloned ${sym.name} from ${sym.owner} into implClass ${implClass.fullName}")
- }
- }
- else {
- log(s"Destructively modifying owner of $sym from ${sym.owner} to $implClass")
- sym.owner = implClass
- // note: OK to destructively modify the owner here,
- // because symbol will not be accessible from outside the sourcefile.
- // mixin constructors are corrected separately; see TermSymbol.owner
- decls enter sym
- }
- }
-
- decls
- }
-
- override def complete(implSym: Symbol) {
- debuglog("LazyImplClassType completing " + implSym)
-
- /* If `tp` refers to a non-interface trait, return a
- * reference to its implementation class. Otherwise return `tp`.
- */
- def mixinToImplClass(tp: Type): Type = AddInterfaces.this.erasure(implSym) {
- tp match { //@MATN: no normalize needed (comes after erasure)
- case TypeRef(pre, sym, _) if sym.needsImplClass =>
- typeRef(pre, implClass(sym), Nil)
- case _ =>
- tp
- }
- }
- def implType(tp: Type): Type = tp match {
- case ClassInfoType(parents, decls, _) =>
- assert(phase == implClassPhase, tp)
- // Impl class parents: Object first, matching interface last.
- val implParents = ObjectTpe +: (parents.tail map mixinToImplClass filter (_.typeSymbol != ObjectClass)) :+ iface.tpe
- ClassInfoType(implParents, implDecls(implSym, decls), implSym)
- case PolyType(_, restpe) =>
- implType(restpe)
- }
- implSym setInfo implType(enteringErasure(iface.info))
- }
-
- override def load(clazz: Symbol) { complete(clazz) }
- }
-
- def transformMixinInfo(tp: Type): Type = tp match {
- case ClassInfoType(parents, decls, clazz) if clazz.isPackageClass || !clazz.isJavaDefined =>
- if (clazz.needsImplClass)
- implClass(clazz setFlag lateINTERFACE) // generate an impl class
-
- val parents1 = parents match {
- case Nil => Nil
- case hd :: tl =>
- assert(!hd.typeSymbol.isTrait, clazz)
- if (clazz.isTrait) ObjectTpe :: tl
- else parents
- }
- val decls1 = scopeTransform(clazz)(
- decls filter (sym =>
- if (clazz.isInterface) isInterfaceMember(sym)
- else sym.isClass || sym.isTerm
- )
- )
- ClassInfoType(parents1, decls1, clazz)
- case _ =>
- tp
- }
-
-// Tree transformation --------------------------------------------------------------
-
- private class ChangeOwnerAndReturnTraverser(oldowner: Symbol, newowner: Symbol)
- extends ChangeOwnerTraverser(oldowner, newowner) {
- override def traverse(tree: Tree) {
- tree match {
- case _: Return => change(tree.symbol)
- case _ =>
- }
- super.traverse(tree)
- }
- }
-
- private def createMemberDef(tree: Tree, isForInterface: Boolean)(create: Tree => Tree) = {
- val isInterfaceTree = tree.isDef && isInterfaceMember(tree.symbol)
- if (isInterfaceTree && needsImplMethod(tree.symbol))
- create(tree)
- else if (isInterfaceTree == isForInterface)
- tree
- else
- EmptyTree
- }
- private def implMemberDef(tree: Tree): Tree = createMemberDef(tree, false)(implMethodDef)
- private def ifaceMemberDef(tree: Tree): Tree = createMemberDef(tree, true)(t => DefDef(t.symbol, EmptyTree))
-
- private def ifaceTemplate(templ: Template): Template =
- treeCopy.Template(templ, templ.parents, noSelfType, templ.body map ifaceMemberDef)
-
- /** Transforms the member tree containing the implementation
- * into a member of the impl class.
- */
- private def implMethodDef(tree: Tree): Tree = {
- val impl = implMethodMap.getOrElse(tree.symbol, abort("implMethod missing for " + tree.symbol))
-
- val newTree = if (impl.isErroneous) tree else { // e.g. res/t687
- // SI-5167: Ensure that the tree that we are grafting refers the parameter symbols from the
- // new method symbol `impl`, rather than the symbols of the original method signature in
- // the trait. `tree setSymbol impl` does *not* suffice!
- val DefDef(_, _, _, vparamss, _, _) = tree
- val oldSyms = vparamss.flatten.map(_.symbol)
- val newSyms = impl.info.paramss.flatten
- assert(oldSyms.length == newSyms.length, (oldSyms, impl, impl.info))
- tree.substituteSymbols(oldSyms, newSyms)
- }
- new ChangeOwnerAndReturnTraverser(newTree.symbol, impl)(newTree setSymbol impl)
- }
-
- /** Add mixin constructor definition
- * def $init$(): Unit = ()
- * to `stats` unless there is already one.
- */
- private def addMixinConstructorDef(clazz: Symbol, stats: List[Tree]): List[Tree] =
- if (treeInfo.firstConstructor(stats) != EmptyTree) stats
- else DefDef(clazz.primaryConstructor, Block(List(), Literal(Constant(())))) :: stats
-
- private def implTemplate(clazz: Symbol, templ: Template): Template = atPos(templ.pos) {
- val templ1 = (
- Template(templ.parents, noSelfType, addMixinConstructorDef(clazz, templ.body map implMemberDef))
- setSymbol clazz.newLocalDummy(templ.pos)
- )
- templ1.changeOwner(templ.symbol.owner -> clazz, templ.symbol -> templ1.symbol)
- templ1
- }
-
- def implClassDefs(trees: List[Tree]): List[Tree] = {
- trees collect {
- case cd: ClassDef if cd.symbol.needsImplClass =>
- val clazz = implClass(cd.symbol).initialize
- ClassDef(clazz, implTemplate(clazz, cd.impl))
- }
- }
-
- /** Add calls to supermixin constructors
- * `super[mix].$init$()`
- * to tree, which is assumed to be the body of a constructor of class clazz.
- */
- private def addMixinConstructorCalls(tree: Tree, clazz: Symbol): Tree = {
- def mixinConstructorCall(impl: Symbol): Tree = atPos(tree.pos) {
- Apply(Select(This(clazz), impl.primaryConstructor), List())
- }
- val mixinConstructorCalls: List[Tree] = {
- for (mc <- clazz.mixinClasses.reverse
- if mc.hasFlag(lateINTERFACE))
- yield mixinConstructorCall(implClass(mc))
- }
- tree match {
- case Block(Nil, expr) =>
- // AnyVal constructor - have to provide a real body so the
- // jvm doesn't throw a VerifyError. But we can't add the
- // body until now, because the typer knows that Any has no
- // constructor and won't accept a call to super.init.
- assert((clazz isSubClass AnyValClass) || clazz.info.parents.isEmpty, clazz)
- Block(List(Apply(gen.mkSuperInitCall, Nil)), expr)
-
- case Block(stats, expr) =>
- // needs `hasSymbolField` check because `supercall` could be a block (named / default args)
- val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER))
- treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr)
- }
- }
-
- protected val mixinTransformer = new Transformer {
- override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
- (super.transformStats(stats, exprOwner) :::
- super.transformStats(implClassDefs(stats), exprOwner))
- override def transform(tree: Tree): Tree = {
- val sym = tree.symbol
- val tree1 = tree match {
- case ClassDef(mods, _, _, impl) if sym.needsImplClass =>
- implClass(sym).initialize // to force lateDEFERRED flags
- copyClassDef(tree)(mods = mods | INTERFACE, impl = ifaceTemplate(impl))
- case DefDef(_,_,_,_,_,_) if sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass =>
- deriveDefDef(tree)(addMixinConstructorCalls(_, sym.owner)) // (3)
- case Template(parents, self, body) =>
- val parents1 = sym.owner.info.parents map (t => TypeTree(t) setPos tree.pos)
- treeCopy.Template(tree, parents1, noSelfType, body)
- case This(_) if sym.needsImplClass =>
- val impl = implClass(sym)
- var owner = currentOwner
- while (owner != sym && owner != impl) owner = owner.owner;
- if (owner == impl) This(impl) setPos tree.pos
- else tree
- //TODO what about this commented out code?
-/* !!!
- case Super(qual, mix) =>
- val mix1 = mix
- if (mix == tpnme.EMPTY) mix
- else {
- val ps = enteringErasure {
- sym.info.parents dropWhile (p => p.symbol.name != mix)
- }
- assert(!ps.isEmpty, tree);
- if (ps.head.symbol.needsImplClass) implClass(ps.head.symbol).name
- else mix
- }
- if (sym.needsImplClass) Super(implClass(sym), mix1) setPos tree.pos
- else treeCopy.Super(tree, qual, mix1)
-*/
- case _ =>
- tree
- }
- super.transform(tree1)
- }
- }
-}