Skip to content

Do not create companions that will be dropped later. #1117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions src/dotty/tools/dotc/core/Phases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down Expand Up @@ -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.
*/
Expand Down
8 changes: 6 additions & 2 deletions src/dotty/tools/dotc/transform/ExtensionMethods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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._
Expand All @@ -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 {
Expand Down
16 changes: 14 additions & 2 deletions src/dotty/tools/dotc/transform/FirstTransform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down Expand Up @@ -32,6 +34,16 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi

override def phaseName = "firstTransform"

private var addCompanionPhases: List[NeedsCompanions] = _

def needsCompanion(cls: ClassSymbol)(implicit ctx: Context) =
addCompanionPhases.exists(_.isCompanionNeeded(cls))

override def prepareForUnit(tree: tpd.Tree)(implicit ctx: Context): TreeTransform = {
addCompanionPhases = ctx.phasePlan.flatMap(_ collect { case p: NeedsCompanions => p })
this
}

def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp

override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = tree match {
Expand Down Expand Up @@ -80,7 +92,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) && needsCompanion(stat.symbol.asClass) =>
val objName = stat.name.toTermName
val nameClash = stats.exists {
case other: MemberDef =>
Expand Down
8 changes: 7 additions & 1 deletion src/dotty/tools/dotc/transform/LazyVals.scala
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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._
Expand All @@ -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)

Expand Down