Skip to content

Commit df7d891

Browse files
committed
New phase to drop empty companion objects
1 parent c16ead8 commit df7d891

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class Compiler {
7777
new GetClass), // getClass transformation should be applied to specialized methods
7878
List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
7979
new ElimStaticThis,
80+
new DropEmptyCompanions,
8081
new Flatten,
8182
new RestoreScopes),
8283
List(/*new PrivateToStatic,*/
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import DenotTransformers.SymTransformer
6+
import Phases.Phase
7+
import Contexts.Context
8+
import Flags._
9+
import Symbols._
10+
import SymDenotations.SymDenotation
11+
import ast.Trees._
12+
import collection.mutable
13+
import Decorators._
14+
import NameOps._
15+
import TreeTransforms.{TreeTransform, MiniPhase}
16+
import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo
17+
18+
/** Remove companion objects that are empty */
19+
class DropEmptyCompanions extends MiniPhase { thisTransform =>
20+
import ast.tpd._
21+
override def phaseName = "dropEmpty"
22+
val treeTransform = new Transform(Set())
23+
24+
class Transform(dropped: Set[Symbol]) extends TreeTransform {
25+
def phase = thisTransform
26+
27+
/** Is `tree` an empty companion object? */
28+
private def isEmptyCompanion(tree: Tree)(implicit ctx: Context) = tree match {
29+
case TypeDef(_, impl: Template) =>
30+
tree.symbol.is(Module) &&
31+
tree.symbol.companionClass.exists &&
32+
impl.body.forall(_.symbol.isPrimaryConstructor)
33+
case _ =>
34+
false
35+
}
36+
37+
/** A transform which has all empty companion objects in `stats`
38+
* recorded in its `dropped` set.
39+
*/
40+
private def localTransform(stats: List[Tree])(implicit ctx: Context) =
41+
new Transform(stats.filter(isEmptyCompanion).map(_.symbol).toSet)
42+
43+
override def prepareForTemplate(tree: Template)(implicit ctx: Context) =
44+
localTransform(tree.body)
45+
46+
override def prepareForStats(trees: List[Tree])(implicit ctx: Context) =
47+
if (ctx.owner is Package) localTransform(trees) else this
48+
49+
/** Symbol is a $lzy field representing a module */
50+
private def isLazyModuleVar(sym: Symbol)(implicit ctx: Context) =
51+
sym.name.isLazyLocal &&
52+
sym.owner.info.decl(sym.name.asTermName.nonLazyName).symbol.is(Module)
53+
54+
/** Symbol should be dropped together with a dropped companion object.
55+
* Such symbols are:
56+
* - lzy fields pointing to modules,
57+
* - vals and getters representing modules.
58+
*/
59+
private def toDrop(sym: Symbol)(implicit ctx: Context): Boolean =
60+
(sym.is(Module) || isLazyModuleVar(sym)) &&
61+
dropped.contains(sym.info.resultType.typeSymbol)
62+
63+
/** Tree should be dropped because it (is associated with) an empty
64+
* companion object. Such trees are
65+
* - module classes of empty companion objects
66+
* - definitions of lazy module variables or assignments to them.
67+
* - vals and getters for empty companion objects
68+
*/
69+
private def toDrop(stat: Tree)(implicit ctx: Context): Boolean = stat match {
70+
case stat: TypeDef => dropped.contains(stat.symbol)
71+
case stat: ValOrDefDef => toDrop(stat.symbol)
72+
case stat: Assign => toDrop(stat.lhs.symbol)
73+
case _ => false
74+
}
75+
76+
override def transformStats(stats: List[Tree])(implicit ctx: Context, info: TransformerInfo) =
77+
stats.filterNot(toDrop)
78+
}
79+
}

src/dotty/tools/dotc/transform/Flatten.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import collection.mutable
1111
import TreeTransforms.MiniPhaseTransform
1212
import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo
1313

14+
/** Lift nested classes to toplevel */
1415
class Flatten extends MiniPhaseTransform with SymTransformer { thisTransform =>
1516
import ast.tpd._
1617
override def phaseName = "flatten"

0 commit comments

Comments
 (0)