Skip to content
Merged
4 changes: 2 additions & 2 deletions src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class Compiler {
def phases: List[List[Phase]] =
List(
List(new FrontEnd),
List(new LazyValsCreateCompanionObjects), //force separataion between lazyVals and LVCreateCO
List(new LazyValTranformContext().transformer, new TypeTestsCasts),
List(new LazyValsCreateCompanionObjects, new PatternMatcher), //force separataion between lazyVals and LVCreateCO
List(new LazyValTranformContext().transformer, new Splitter, new TypeTestsCasts),
List(new Erasure),
List(new UncurryTreeTransform)
)
Expand Down
12 changes: 7 additions & 5 deletions src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Contexts._, Periods._, Symbols._, Phases._, Decorators._
import io.PlainFile
import util.{SourceFile, NoSource, Stats, SimpleMap}
import reporting.Reporter
import transform.TreeChecker
import java.io.{BufferedWriter, OutputStreamWriter}
import scala.reflect.io.VirtualFile

Expand Down Expand Up @@ -39,18 +40,19 @@ class Run(comp: Compiler)(implicit ctx: Context) {
for (phase <- phasesToRun) {
if (!ctx.reporter.hasErrors) {
phase.runOn(units)
if (ctx.settings.Xprint.value.containsPhase(phase))
for (unit <- units)
printTree(ctx.fresh.setPhase(phase).setCompilationUnit(unit))
def foreachUnit(op: Context => Unit)(implicit ctx: Context): Unit =
for (unit <- units) op(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit))
if (ctx.settings.Xprint.value.containsPhase(phase)) foreachUnit(printTree)
if (ctx.settings.Ycheck.value.containsPhase(phase)) foreachUnit(TreeChecker.check)
}
}
}
}

private def printTree(implicit ctx: Context) = {
private def printTree(ctx: Context) = {
val unit = ctx.compilationUnit
println(s"result of $unit after ${ctx.phase}:")
println(unit.tpdTree.show)
println(unit.tpdTree.show(ctx))
}

def compile(sourceCode: String): Unit = {
Expand Down
13 changes: 10 additions & 3 deletions src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
import CheckTrees._, Denotations._, Decorators._
import config.Printers._
import typer.ErrorReporting._

/** Some creators for typed trees */
object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Expand Down Expand Up @@ -400,11 +401,17 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}

// convert a numeric with a toXXX method
def numericConversion(tree: Tree, numericCls: Symbol)(implicit ctx: Context): Tree = {
def primitiveConversion(tree: Tree, numericCls: Symbol)(implicit ctx: Context): Tree = {
val mname = ("to" + numericCls.name).toTermName
val conversion = tree.tpe member mname
assert(conversion.symbol.exists, s"$tree => $numericCls")
ensureApplied(Select(tree, conversion.symbol.termRef))
if (conversion.symbol.exists)
ensureApplied(Select(tree, conversion.symbol.termRef))
else if (tree.tpe.widen isRef numericCls)
tree
else {
ctx.warning(i"conversion from ${tree.tpe.widen} to ${numericCls.typeRef} will always fail at runtime.")
Throw(New(defn.ClassCastExceptionClass.typeRef, Nil)) withPos tree.pos
}
}

def evalOnce(tree: Tree)(within: Tree => Tree)(implicit ctx: Context) = {
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class ScalaSettings extends Settings.SettingGroup {
val overrideVars = BooleanSetting("-Yoverride-vars", "Allow vars to be overridden.")
val Yhelp = BooleanSetting("-Y", "Print a synopsis of private options.")
val browse = PhasesSetting("-Ybrowse", "Browse the abstract syntax tree after")
val check = PhasesSetting("-Ycheck", "Check the tree at the end of")
val Ycheck = PhasesSetting("-Ycheck", "Check the tree at the end of")
val YcheckTypedTrees = BooleanSetting("-YcheckTypedTrees", "Check all constructured typed trees for type correctness")
val Yshow = PhasesSetting("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after")
val Xcloselim = BooleanSetting("-Yclosure-elim", "Perform closure elimination.")
Expand Down
1 change: 0 additions & 1 deletion src/dotty/tools/dotc/config/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ object Settings {
setting
}


def BooleanSetting(name: String, descr: String): Setting[Boolean] =
publish(Setting(name, descr, false))

Expand Down
58 changes: 38 additions & 20 deletions src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,30 @@ object Contexts {
protected def searchHistory_= (searchHistory: SearchHistory) = _searchHistory = searchHistory
def searchHistory: SearchHistory = _searchHistory

private var phasedCtx: Context = _
private var phasedCtxs: Array[Context] = _


/** This context at given phase.
* This method will always return a phase period equal to phaseId, thus will never return squashed phases
*/
final def withPhase(phaseId: PhaseId): Context = {
if (this.phaseId == phaseId) this
else if (phasedCtx.phaseId == phaseId) phasedCtx
else if (phasedCtxs != null && phasedCtxs(phaseId) != null) phasedCtxs(phaseId)
else {
val ctx1 = fresh.setPhase(phaseId)
if (phasedCtx eq this) phasedCtx = ctx1
else {
if (phasedCtxs == null) phasedCtxs = new Array[Context](base.phases.length)
phasedCtxs(phaseId) = ctx1
}
ctx1
}
}

final def withPhase(phase: Phase): Context =
withPhase(phase.id)
/** If -Ydebug is on, the top of the stack trace where this context
* was created, otherwise `null`.
*/
Expand Down Expand Up @@ -266,29 +290,23 @@ object Contexts {
}
*/

/** A fresh clone of this context. */
def fresh: FreshContext = {
val newctx: Context = super.clone.asInstanceOf[FreshContext]
newctx.outer = this
newctx.implicitsCache = null
newctx.setCreationTrace()
// Dotty deviation: Scala2x allows access to private members implicitCache and setCreationTrace
// even from a subclass prefix. Dotty (and Java) do not. It's confirmed as a bug in Scala2x.
newctx.asInstanceOf[FreshContext]
protected def init(outer: Context): this.type = {
this.outer = outer
this.implicitsCache = null
this.phasedCtx = this
this.phasedCtxs = null
setCreationTrace()
this
}
/** A fresh clone of this context. */
def fresh: FreshContext = clone.asInstanceOf[FreshContext].init(this)

final def withOwner(owner: Symbol): Context =
if (owner ne this.owner) fresh.setOwner(owner) else this

final def withMode(mode: Mode): Context =
if (mode != this.mode) fresh.setMode(mode) else this

/**
* This method will always return a phase period equal to phaseId, thus will never return squashed phases
*/
final def withPhase(phaseId: PhaseId): Context =
if (this.phaseId == phaseId) this else fresh.setPhase(phaseId)
final def withPhase(phase: Phase): Context =
if (this.period == phase.period) this else fresh.setPhase(phase)


final def addMode(mode: Mode): Context = withMode(this.mode | mode)
final def maskMode(mode: Mode): Context = withMode(this.mode & mode)
final def retractMode(mode: Mode): Context = withMode(this.mode &~ mode)
Expand All @@ -313,15 +331,15 @@ object Contexts {
def setPeriod(period: Period): this.type = { this.period = period; this }
def setMode(mode: Mode): this.type = { this.mode = mode; this }
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
def clearTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))
def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))
def setExploreTyperState: this.type = setTyperState(typerState.fresh(isCommittable = false))
def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
def setOwner(owner: Symbol): this.type = { assert(owner != NoSymbol); this.owner = owner; this }
def setSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this }
def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { this.compilationUnit = compilationUnit; this }
def setTree(tree: Tree[_ >: Untyped]): this.type = { this.tree = tree; this }
def setScope(scope: Scope): this.type = { this.scope = scope; this }
def clearScope: this.type = { this.scope = newScope; this }
def setNewScope: this.type = { this.scope = newScope; this }
def setTypeAssigner(typeAssigner: TypeAssigner): this.type = { this.typeAssigner = typeAssigner; this }
def setTyper(typer: Typer): this.type = { this.scope = typer.scope; setTypeAssigner(typer) }
def setImportInfo(importInfo: ImportInfo): this.type = { this.importInfo = importInfo; this }
Expand Down
7 changes: 5 additions & 2 deletions src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Symbols._
import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer
import util.Positions.Position, util.SourcePosition
import collection.mutable.ListBuffer
import dotty.tools.dotc.transform.TreeTransforms._
import scala.language.implicitConversions

/** This object provides useful implicit decorators for types defined elsewhere */
Expand Down Expand Up @@ -127,8 +128,10 @@ object Decorators {
* one of the names in the list of strings.
*/
implicit class PhaseListDecorator(val names: List[String]) extends AnyVal {
def containsPhase(phase: Phase) =
names exists (phase.name.startsWith)
def containsPhase(phase: Phase): Boolean = phase match {
case phase: TreeTransformer => phase.transformations.exists(containsPhase)
case _ => names exists (phase.name.startsWith)
}
}

implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition =
Expand Down
5 changes: 3 additions & 2 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ class Definitions {
lazy val Object_!= = newMethod(ObjectClass, nme.NE, methOfAny(BooleanType), Final)
lazy val Object_eq = newMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final)
lazy val Object_ne = newMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final)
lazy val Object_isInstanceOf = newT1EmptyParamsMethod(ObjectClass, nme.isInstanceOf_Ob, _ => BooleanType, Final | Synthetic)
lazy val Object_asInstanceOf = newT1EmptyParamsMethod(ObjectClass, nme.asInstanceOf_Ob, PolyParam(_, 0), Final | Synthetic)
lazy val Object_isInstanceOf = newT1ParameterlessMethod(ObjectClass, nme.isInstanceOf_Ob, _ => BooleanType, Final | Synthetic)
lazy val Object_asInstanceOf = newT1ParameterlessMethod(ObjectClass, nme.asInstanceOf_Ob, PolyParam(_, 0), Final | Synthetic)
lazy val Object_synchronized = newPolyMethod(ObjectClass, nme.synchronized_, 1,
pt => MethodType(List(PolyParam(pt, 0)), PolyParam(pt, 0)), Final)

Expand Down Expand Up @@ -218,6 +218,7 @@ class Definitions {
lazy val OptionClass = ctx.requiredClass("scala.Option")
lazy val BoxedNumberClass = ctx.requiredClass("java.lang.Number")
lazy val ThrowableClass = ctx.requiredClass("java.lang.Throwable")
lazy val ClassCastExceptionClass = ctx.requiredClass("java.lang.ClassCastException")
lazy val JavaSerializableClass = ctx.requiredClass("java.lang.Serializable")
lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable")
lazy val ProductClass = ctx.requiredClass("scala.Product")
Expand Down
4 changes: 2 additions & 2 deletions src/dotty/tools/dotc/core/Phases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ object Phases {
postTyperEmmited = true
new PostTyperTransformer {
override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}")
override protected def transformations: Array[TreeTransform] = transforms.toArray
override def transformations: Array[TreeTransform] = transforms.toArray
}
} else new TreeTransformer {
override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}")
override protected def transformations: Array[TreeTransform] = transforms.toArray
override def transformations: Array[TreeTransform] = transforms.toArray
}
squashedPhases += block
block.init(this, phasess(i).head.id, phasess(i).last.id)
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ object SymDenotations {
myFlags |= Touched

// completions.println(s"completing ${this.debugString}")
try completer.complete(this)
try completer.complete(this)(ctx.withPhase(validFor.firstPhaseId))
catch {
case ex: CyclicReference =>
completions.println(s"error while completing ${this.debugString}")
Expand Down
11 changes: 8 additions & 3 deletions src/dotty/tools/dotc/core/TypeApplications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import TypeApplications._
/** A decorator that provides methods for modeling type application */
class TypeApplications(val self: Type) extends AnyVal {

def canHaveTypeParams(implicit ctx: Context) = !ctx.erasedTypes || self.isRef(defn.ArrayClass)

/** The type parameters of this type are:
* For a ClassInfo type, the type parameters of its class.
* For a typeref referring to a class, the type parameters of the class.
Expand Down Expand Up @@ -128,7 +130,7 @@ class TypeApplications(val self: Type) extends AnyVal {
defn.hkTrait(args map alwaysZero).typeParams
}

if (args.isEmpty) self
if (args.isEmpty || !canHaveTypeParams) self
else self match {
case tp: TypeRef =>
val tsym = tp.symbol
Expand Down Expand Up @@ -228,8 +230,11 @@ class TypeApplications(val self: Type) extends AnyVal {
* `from` and `to` must be static classes, both with one type parameter, and the same variance.
*/
def translateParameterized(from: ClassSymbol, to: ClassSymbol)(implicit ctx: Context): Type =
if (self derivesFrom from)
RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info)
if (self.derivesFrom(from))
if (canHaveTypeParams)
RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info)
else
to.typeRef
else self

/** If this is an encoding of a (partially) applied type, return its arguments,
Expand Down
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,7 @@ object Types {
}
lastDenotation = d
lastSymbol = d.symbol
checkedPeriod = ctx.period
d
}

Expand Down
17 changes: 6 additions & 11 deletions src/dotty/tools/dotc/core/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,11 @@ object Erasure {
*/
def transformInfo(sym: Symbol, tp: Type)(implicit ctx: Context): Type = {
val erase = erasureFn(sym is JavaDefined, isSemi = true, sym.isConstructor, wildcardOK = false)
if ((sym eq defn.Object_asInstanceOf) || sym.isType && (sym.owner eq defn.ArrayClass))
sym.info
else if ((sym eq defn.Object_isInstanceOf) || (sym eq defn.ArrayClass.primaryConstructor)) {
val tp @ PolyType(pnames) = sym.info
tp.derivedPolyType(pnames, TypeBounds.empty :: Nil, erase(tp.resultType))
}
else if (sym.isAbstractType)
TypeAlias(WildcardType)
else
erase(tp)
if ((sym eq defn.Object_asInstanceOf) ||
(sym eq defn.Object_isInstanceOf) ||
(sym.owner eq defn.ArrayClass) && (sym.isType || sym.isConstructor)) sym.info
else if (sym.isAbstractType) TypeAlias(WildcardType)
else erase(tp)
}

def isUnboundedGeneric(tp: Type)(implicit ctx: Context) = !(
Expand Down Expand Up @@ -120,7 +115,7 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard
case tp: TypeRef =>
val sym = tp.symbol
if (!sym.isClass)
if (sym.owner eq defn.ArrayClass) tp else this(tp.info)
if (sym.exists && (sym.owner eq defn.ArrayClass)) tp else this(tp.info) //!!!!
else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tp)
else eraseNormalClassRef(tp)
case tp: RefinedType =>
Expand Down
Loading