aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-02-11 09:17:07 +0100
committerMartin Odersky <odersky@gmail.com>2016-02-11 09:17:15 +0100
commitdf7d8914aa139e8961db6ce0651e09b118d8bab2 (patch)
tree4285b0d129e7869dc9f727f379a293ab36fc6254 /src/dotty/tools
parentc16ead8d78936cab3dada7aa5e70eeacc5f576d1 (diff)
downloaddotty-df7d8914aa139e8961db6ce0651e09b118d8bab2.tar.gz
dotty-df7d8914aa139e8961db6ce0651e09b118d8bab2.tar.bz2
dotty-df7d8914aa139e8961db6ce0651e09b118d8bab2.zip
New phase to drop empty companion objects
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/Compiler.scala1
-rw-r--r--src/dotty/tools/dotc/transform/DropEmptyCompanions.scala79
-rw-r--r--src/dotty/tools/dotc/transform/Flatten.scala1
3 files changed, 81 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 199657864..987c533e7 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -77,6 +77,7 @@ class Compiler {
new GetClass), // getClass transformation should be applied to specialized methods
List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
new ElimStaticThis,
+ new DropEmptyCompanions,
new Flatten,
new RestoreScopes),
List(/*new PrivateToStatic,*/
diff --git a/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala
new file mode 100644
index 000000000..05296d93e
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala
@@ -0,0 +1,79 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import DenotTransformers.SymTransformer
+import Phases.Phase
+import Contexts.Context
+import Flags._
+import Symbols._
+import SymDenotations.SymDenotation
+import ast.Trees._
+import collection.mutable
+import Decorators._
+import NameOps._
+import TreeTransforms.{TreeTransform, MiniPhase}
+import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo
+
+/** Remove companion objects that are empty */
+class DropEmptyCompanions extends MiniPhase { thisTransform =>
+ import ast.tpd._
+ override def phaseName = "dropEmpty"
+ val treeTransform = new Transform(Set())
+
+ class Transform(dropped: Set[Symbol]) extends TreeTransform {
+ def phase = thisTransform
+
+ /** Is `tree` an empty companion object? */
+ private def isEmptyCompanion(tree: Tree)(implicit ctx: Context) = tree match {
+ case TypeDef(_, impl: Template) =>
+ tree.symbol.is(Module) &&
+ tree.symbol.companionClass.exists &&
+ impl.body.forall(_.symbol.isPrimaryConstructor)
+ case _ =>
+ false
+ }
+
+ /** A transform which has all empty companion objects in `stats`
+ * recorded in its `dropped` set.
+ */
+ private def localTransform(stats: List[Tree])(implicit ctx: Context) =
+ new Transform(stats.filter(isEmptyCompanion).map(_.symbol).toSet)
+
+ override def prepareForTemplate(tree: Template)(implicit ctx: Context) =
+ localTransform(tree.body)
+
+ override def prepareForStats(trees: List[Tree])(implicit ctx: Context) =
+ if (ctx.owner is Package) localTransform(trees) else this
+
+ /** Symbol is a $lzy field representing a module */
+ private def isLazyModuleVar(sym: Symbol)(implicit ctx: Context) =
+ sym.name.isLazyLocal &&
+ sym.owner.info.decl(sym.name.asTermName.nonLazyName).symbol.is(Module)
+
+ /** Symbol should be dropped together with a dropped companion object.
+ * Such symbols are:
+ * - lzy fields pointing to modules,
+ * - vals and getters representing modules.
+ */
+ private def toDrop(sym: Symbol)(implicit ctx: Context): Boolean =
+ (sym.is(Module) || isLazyModuleVar(sym)) &&
+ dropped.contains(sym.info.resultType.typeSymbol)
+
+ /** Tree should be dropped because it (is associated with) an empty
+ * companion object. Such trees are
+ * - module classes of empty companion objects
+ * - definitions of lazy module variables or assignments to them.
+ * - vals and getters for empty companion objects
+ */
+ private def toDrop(stat: Tree)(implicit ctx: Context): Boolean = stat match {
+ case stat: TypeDef => dropped.contains(stat.symbol)
+ case stat: ValOrDefDef => toDrop(stat.symbol)
+ case stat: Assign => toDrop(stat.lhs.symbol)
+ case _ => false
+ }
+
+ override def transformStats(stats: List[Tree])(implicit ctx: Context, info: TransformerInfo) =
+ stats.filterNot(toDrop)
+ }
+}
diff --git a/src/dotty/tools/dotc/transform/Flatten.scala b/src/dotty/tools/dotc/transform/Flatten.scala
index 9a047ef95..f0104e715 100644
--- a/src/dotty/tools/dotc/transform/Flatten.scala
+++ b/src/dotty/tools/dotc/transform/Flatten.scala
@@ -11,6 +11,7 @@ import collection.mutable
import TreeTransforms.MiniPhaseTransform
import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo
+/** Lift nested classes to toplevel */
class Flatten extends MiniPhaseTransform with SymTransformer { thisTransform =>
import ast.tpd._
override def phaseName = "flatten"