aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDmitry Petrashko <dmitry.petrashko@gmail.com>2016-02-20 15:31:11 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2016-02-20 17:42:17 +0100
commit910481a0f4fe671f3f4d8965eac61870596970e1 (patch)
treee7e43723a83b279b23737c2fe5139dd30c9e9e8a /src
parent6e535f7dc855d1587142f81bd9a53ea9ba3c7300 (diff)
downloaddotty-910481a0f4fe671f3f4d8965eac61870596970e1.tar.gz
dotty-910481a0f4fe671f3f4d8965eac61870596970e1.tar.bz2
dotty-910481a0f4fe671f3f4d8965eac61870596970e1.zip
Do not create companions that will be dropped later.
Fix blocker bug reported in #1114 I dislike this fix as now phase needs to know in advance if it will ever need a companion for the class. On the bright side, this change makes it clear which phases need companions
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/Compiler.scala2
-rw-r--r--src/dotty/tools/dotc/core/Phases.scala5
-rw-r--r--src/dotty/tools/dotc/transform/ExtensionMethods.scala8
-rw-r--r--src/dotty/tools/dotc/transform/FirstTransform.scala14
-rw-r--r--src/dotty/tools/dotc/transform/LazyVals.scala8
5 files changed, 31 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 99b7bd880..d526903b8 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -78,7 +78,7 @@ class Compiler {
List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
new ElimStaticThis,
new Flatten,
- new DropEmptyCompanions,
+ // new DropEmptyCompanions,
new RestoreScopes),
List(new ExpandPrivate,
new CollectEntryPoints,
diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala
index 83ac64d53..b60f437d5 100644
--- a/src/dotty/tools/dotc/core/Phases.scala
+++ b/src/dotty/tools/dotc/core/Phases.scala
@@ -4,6 +4,7 @@ package core
import Periods._
import Contexts._
import dotty.tools.backend.jvm.{LabelDefs, GenBCode}
+import dotty.tools.dotc.core.Symbols.ClassSymbol
import util.DotClass
import DenotTransformers._
import Denotations._
@@ -347,6 +348,10 @@ object Phases {
override def toString = phaseName
}
+ trait NeedsCompanions {
+ def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean
+ }
+
/** Replace all instances of `oldPhaseClass` in `current` phases
* by the result of `newPhases` applied to the old phase.
*/
diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
index 90e105ee7..c5ab49c9c 100644
--- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala
+++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
@@ -11,7 +11,7 @@ import dotty.tools.dotc.ast.{Trees, tpd}
import scala.collection.{ mutable, immutable }
import mutable.ListBuffer
import core._
-import Phases.Phase
+import dotty.tools.dotc.core.Phases.{NeedsCompanions, Phase}
import Types._, Contexts._, Constants._, Names._, NameOps._, Flags._, DenotTransformers._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Scopes._, Denotations._
import TypeErasure.{ valueErasure, ErasedValueType }
@@ -33,7 +33,7 @@ import SymUtils._
* This is different from the implementation of value classes in Scala 2
* (see SIP-15) which uses `asInstanceOf` which does not typecheck.
*/
-class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization { thisTransformer =>
+class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with FullParameterization with NeedsCompanions { thisTransformer =>
import tpd._
import ExtensionMethods._
@@ -45,6 +45,10 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
override def runsAfterGroupsOf = Set(classOf[FirstTransform]) // need companion objects to exist
+ def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean = {
+ isDerivedValueClass(cls)
+ }
+
override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
case moduleClassSym: ClassDenotation if moduleClassSym is ModuleClass =>
moduleClassSym.linkedClass match {
diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala
index 3b629f9b6..5d42d4c16 100644
--- a/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -3,7 +3,9 @@ package transform
import core._
import Names._
-import dotty.tools.dotc.transform.TreeTransforms.{AnnotationTransformer, TransformerInfo, MiniPhaseTransform, TreeTransformer}
+import dotty.tools.dotc.ast.tpd
+import dotty.tools.dotc.core.Phases.NeedsCompanions
+import dotty.tools.dotc.transform.TreeTransforms._
import ast.Trees._
import Flags._
import Types._
@@ -32,6 +34,14 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
override def phaseName = "firstTransform"
+ private var needsCompanionPredicate: ClassSymbol => Boolean = null
+
+ override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
+ needsCompanionPredicate = ctx.phasePlan.flatMap(_.filter(x => x.isInstanceOf[NeedsCompanions])).
+ foldLeft((x: ClassSymbol) => false)((pred, phase) => x => pred(x) || phase.asInstanceOf[NeedsCompanions].isCompanionNeeded(x))
+ this
+ }
+
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp
override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
@@ -80,7 +90,7 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
}
def addMissingCompanions(stats: List[Tree]): List[Tree] = stats map {
- case stat: TypeDef if singleClassDefs contains stat.name =>
+ case stat: TypeDef if (singleClassDefs contains stat.name) && needsCompanionPredicate(stat.symbol.asClass) =>
val objName = stat.name.toTermName
val nameClash = stats.exists {
case other: MemberDef =>
diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala
index 4a8ff83ca..2aece0663 100644
--- a/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -1,6 +1,7 @@
package dotty.tools.dotc
package transform
+import dotty.tools.dotc.core.Phases.NeedsCompanions
import dotty.tools.dotc.typer.Mode
import scala.collection.mutable
@@ -23,7 +24,7 @@ import dotty.tools.dotc.core.SymDenotations.SymDenotation
import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, IdentityDenotTransformer, DenotTransformer}
import Erasure.Boxing.adaptToType
-class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
+class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer with NeedsCompanions {
import LazyVals._
import tpd._
@@ -46,6 +47,11 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
* before this phase starts processing same tree */
override def runsAfter = Set(classOf[Mixin])
+ def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean = {
+ def hasLazyVal(x: ClassSymbol) = x.classInfo.membersBasedOnFlags(Flags.Lazy, excludedFlags = Flags.EmptyFlags).nonEmpty
+ hasLazyVal(cls) || cls.mixins.exists(hasLazyVal)
+ }
+
override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree =
transformLazyVal(tree)